Handle destroyed stream in packet dispatcher.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 18 Dec 2006 14:49:05 +0000 (14:49 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 18 Dec 2006 14:49:05 +0000 (14:49 +0000)
lib/silccore/silcmessage.c
lib/silccore/silcpacket.c

index be06879ec99bbdd357afebd152dce2bb09dc30a7..19c1959effe1f3f298b90bd43c11d09f9de35690 100644 (file)
@@ -65,7 +65,7 @@ SilcUInt32 silc_message_payload_datalen(SilcUInt32 data_len,
                      silc_pkcs_private_key_get_len(private_key) / 8 : 0);
   SilcUInt32 dlen = data_len + SILC_MESSAGE_HLEN + header_len + pklen + prlen;
 
-  if (dlen > SILC_MESSAGE_MAX_LEN)
+  if (silc_unlikely(dlen > SILC_MESSAGE_MAX_LEN))
     data_len -= (dlen - SILC_MESSAGE_MAX_LEN);
 
   return data_len;
@@ -281,16 +281,16 @@ SilcBool silc_message_payload_decrypt(unsigned char *data,
   if (!private_message || (private_message && static_key))
     iv_len = block_len;
 
-  if (data_len < (mac_len + iv_len + block_len))
+  if (silc_unlikely(data_len < (mac_len + iv_len + block_len)))
     return FALSE;
 
-  if (check_mac) {
+  if (silc_likely(check_mac)) {
     /* Check the MAC of the message */
     SILC_LOG_DEBUG(("Checking message MAC"));
     silc_hmac_init(hmac);
     silc_hmac_update(hmac, data, data_len - mac_len);
     silc_hmac_final(hmac, mac, &mac_len);
-    if (memcmp(data + (data_len - mac_len), mac, mac_len)) {
+    if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
       SILC_LOG_DEBUG(("Message MAC does not match"));
       return FALSE;
     }
@@ -306,7 +306,8 @@ SilcBool silc_message_payload_decrypt(unsigned char *data,
         silc_cipher_get_iv(cipher));
 
   /* Decrypt block */
-  if (!silc_cipher_decrypt(cipher, data, data, block_len, ivp)) {
+  if (silc_unlikely(!silc_cipher_decrypt(cipher, data, data, block_len,
+                                        ivp))) {
     SILC_ASSERT(FALSE);
     return FALSE;
   }
@@ -315,13 +316,14 @@ SilcBool silc_message_payload_decrypt(unsigned char *data,
   totlen = 2;
   SILC_GET16_MSB(len, data + totlen);
   totlen += 2 + len;
-  if (totlen + iv_len + mac_len + 2 > data_len)
+  if (silc_unlikely(totlen + iv_len + mac_len + 2 > data_len))
     return FALSE;
   totlen += 2;
   if (totlen >= block_len)
-    if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
-                            (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
-                            ivp)) {
+    if (silc_unlikely(!silc_cipher_decrypt(cipher, data + block_len,
+                                          data + block_len,
+                                          (totlen - block_len) +
+                                          SILC_MESSAGE_PAD(totlen), ivp))) {
       SILC_ASSERT(FALSE);
       return FALSE;
     }
@@ -353,15 +355,15 @@ silc_message_payload_parse(unsigned char *payload,
   silc_buffer_set(&buffer, payload, payload_len);
 
   /* Decrypt the payload */
-  if (cipher) {
+  if (silc_likely(cipher)) {
     ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
                                       private_message, static_key,
                                       cipher, hmac, TRUE);
-    if (ret == FALSE)
+    if (silc_unlikely(ret == FALSE))
       return NULL;
   }
 
-  if (hmac)
+  if (silc_likely(hmac))
     mac_len = silc_hmac_len(hmac);
 
   /* IV is present for all channel messages, and private messages when
@@ -371,7 +373,7 @@ silc_message_payload_parse(unsigned char *payload,
 
   if (!message) {
     newp = message = silc_calloc(1, sizeof(*newp));
-    if (!newp)
+    if (silc_unlikely(!newp))
       return NULL;
   }
   memset(message, 0, sizeof(*message));
@@ -394,12 +396,13 @@ silc_message_payload_parse(unsigned char *payload,
                               SILC_STR_UI16_NSTRING(&message->pad,
                                                     &message->pad_len),
                               SILC_STR_END);
-  if (ret == -1)
+  if (silc_unlikely(ret == -1))
     goto err;
 
-  if ((message->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
-      (message->pad_len + message->data_len > silc_buffer_len(&buffer) -
-       6 - mac_len - iv_len)) {
+  if (silc_unlikely((message->data_len > silc_buffer_len(&buffer) -
+                    6 - mac_len - iv_len) ||
+                   (message->pad_len + message->data_len >
+                    silc_buffer_len(&buffer) - 6 - mac_len - iv_len))) {
     SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
     goto err;
   }
@@ -447,7 +450,7 @@ SilcBool silc_message_payload_encrypt(unsigned char *data,
                                      SilcHmac hmac)
 {
   /* Encrypt payload of the packet */
-  if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
+  if (silc_unlikely(!silc_cipher_encrypt(cipher, data, data, data_len, iv)))
     return FALSE;
 
   /* Compute the MAC of the encrypted message data */
@@ -470,13 +473,13 @@ static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
     return 0;
 
   mac_len = silc_hmac_len(e->hmac);
-  if (!silc_buffer_enlarge(buffer, mac_len))
+  if (silc_unlikely(!silc_buffer_enlarge(buffer, mac_len)))
     return -1;
 
-  if (!silc_message_payload_encrypt(buffer->head,
-                                   e->payload_len,
-                                   silc_buffer_headlen(buffer),
-                                   e->iv, e->cipher, e->hmac))
+  if (silc_unlikely(!silc_message_payload_encrypt(buffer->head,
+                                                 e->payload_len,
+                                                 silc_buffer_headlen(buffer),
+                                                 e->iv, e->cipher, e->hmac)))
     return -1;
 
   return mac_len;
@@ -498,14 +501,14 @@ static int silc_message_payload_encode_sig(SilcBuffer buffer,
                                           silc_buffer_headlen(buffer),
                                           e->public_key, e->private_key,
                                           e->hash);
-  if (!sig)
+  if (silc_unlikely(!sig))
     return -1;
 
   len = silc_buffer_format(buffer,
                           SILC_STR_DATA(silc_buffer_data(sig),
                                         silc_buffer_len(sig)),
                           SILC_STR_END);
-  if (len < 0) {
+  if (silc_unlikely(len < 0)) {
     silc_buffer_free(sig);
     return -1;
   }
@@ -537,14 +540,14 @@ SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
 
   SILC_LOG_DEBUG(("Encoding Message Payload"));
 
-  if (!data_len)
+  if (silc_unlikely(!data_len))
     return NULL;
-  if (!private_message && (!cipher || !hmac))
+  if (silc_unlikely(!private_message && (!cipher || !hmac)))
     return NULL;
 
   if (!buffer) {
     buf = buffer = silc_buffer_alloc(0);
-    if (!buf)
+    if (silc_unlikely(!buf))
       return NULL;
   }
   silc_buffer_reset(buffer);
index 98e4b72d4f3c36f6457f546a396fdc7cb99afe45..a88bbf63602155309e8e2fe8522bd193c3f473f8 100644 (file)
@@ -151,7 +151,7 @@ do {                                                                        \
                                (s)->stream_context);                   \
 } while(0)
 
-static void silc_packet_dispatch(SilcPacket packet);
+static SilcBool silc_packet_dispatch(SilcPacket packet);
 static void silc_packet_read_process(SilcPacketStream stream);
 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
                                            SilcPacketType type,
@@ -179,8 +179,10 @@ SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
   SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
 
   silc_mutex_lock(stream->lock);
-  silc_packet_dispatch(packet);
+  if (!stream->destroyed)
+    silc_packet_dispatch(packet);
   silc_mutex_unlock(stream->lock);
+  silc_packet_stream_unref(stream);
 }
 
 /* Write data to the stream.  Must be called with ps->lock locked.  Unlocks
@@ -436,6 +438,7 @@ static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
       return;
 
     /* Now process the data */
+    silc_packet_stream_ref(ps);
     if (!remote) {
       silc_packet_read_process(ps);
       silc_mutex_unlock(ps->lock);
@@ -443,6 +446,7 @@ static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
       silc_packet_read_process(remote);
       silc_mutex_unlock(remote->lock);
     }
+    silc_packet_stream_unref(ps);
     break;
 
   default:
@@ -725,6 +729,7 @@ SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
   if (packet) {
     /* Inject packet to the new stream */
     packet->stream = ps;
+    silc_packet_stream_ref(ps);
     silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
                                   silc_packet_stream_inject_packet, packet,
                                   0, 0);
@@ -1664,9 +1669,10 @@ static inline SilcBool silc_packet_parse(SilcPacket packet)
   return TRUE;
 }
 
-/* Dispatch packet to application.  Called with stream->lock locked. */
+/* Dispatch packet to application.  Called with stream->lock locked.
+   Returns FALSE if the stream was destroyed while dispatching a packet. */
 
-static void silc_packet_dispatch(SilcPacket packet)
+static SilcBool silc_packet_dispatch(SilcPacket packet)
 {
   SilcPacketStream stream = packet->stream;
   SilcPacketProcess p;
@@ -1685,7 +1691,7 @@ static void silc_packet_dispatch(SilcPacket packet)
                                     stream->stream_context)))
       silc_packet_free(packet);
     silc_mutex_lock(stream->lock);
-    return;
+    return stream->destroyed == FALSE;
   }
 
   silc_dlist_start(stream->process);
@@ -1702,7 +1708,7 @@ static void silc_packet_dispatch(SilcPacket packet)
                         stream->engine->callback_context,
                         stream->stream_context)) {
        silc_mutex_lock(stream->lock);
-       return;
+       return stream->destroyed == FALSE;
       }
       silc_mutex_lock(stream->lock);
     }
@@ -1716,7 +1722,7 @@ static void silc_packet_dispatch(SilcPacket packet)
                                       p->callback_context,
                                       stream->stream_context)) {
        silc_mutex_lock(stream->lock);
-       return;
+       return stream->destroyed == FALSE;
       }
       silc_mutex_lock(stream->lock);
     } else {
@@ -1730,7 +1736,7 @@ static void silc_packet_dispatch(SilcPacket packet)
                                         p->callback_context,
                                         stream->stream_context)) {
          silc_mutex_lock(stream->lock);
-         return;
+         return stream->destroyed == FALSE;
        }
        silc_mutex_lock(stream->lock);
        break;
@@ -1747,13 +1753,14 @@ static void silc_packet_dispatch(SilcPacket packet)
                       stream->engine->callback_context,
                       stream->stream_context)) {
       silc_mutex_lock(stream->lock);
-      return;
+      return stream->destroyed == FALSE;
     }
     silc_mutex_lock(stream->lock);
   }
 
   /* If we got here, no one wanted the packet, so drop it */
   silc_packet_free(packet);
+  return stream->destroyed == FALSE;
 }
 
 /* Process incoming data and parse packets.  Called with stream->lock
@@ -1965,7 +1972,8 @@ static void silc_packet_read_process(SilcPacketStream stream)
     }
 
     /* Dispatch the packet to application */
-    silc_packet_dispatch(packet);
+    if (!silc_packet_dispatch(packet))
+      break;
   }
 
   silc_buffer_reset(&stream->inbuf);
@@ -2010,7 +2018,7 @@ silc_packet_wait_packet_receive(SilcPacketEngine engine,
   /* Signal the waiting thread for a new packet */
   silc_mutex_lock(pw->wait_lock);
 
-  if (pw->stopped) {
+  if (silc_unlikely(pw->stopped)) {
     silc_mutex_unlock(pw->wait_lock);
     return FALSE;
   }
@@ -2103,7 +2111,7 @@ int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
 
   /* Wait here until packet has arrived */
   while (silc_list_count(pw->packet_queue) == 0) {
-    if (pw->stopped) {
+    if (silc_unlikely(pw->stopped)) {
       silc_mutex_unlock(pw->wait_lock);
       return -1;
     }