Optimized the socket referencing in packet processing.
[silc.git] / lib / silccore / silcpacket.c
index 1c71b0b51de246ef6aa0c4444ec2807e4ef23131..58f090b9ab64a0c6652e8f2e44c3cba6bc2dd743 100644 (file)
@@ -323,10 +323,12 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     mac_len = silc_hmac_len(hmac);
 
   /* Parse the packets from the data */
+  silc_socket_dup(sock);
   while (sock->inbuf->len > 0 && cont) {
 
     if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
+      silc_socket_free(sock);
       return TRUE;
     }
 
@@ -349,6 +351,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
       SILC_LOG_ERROR(("Received too short packet"));
       memset(header, 0, sizeof(header));
       silc_buffer_clear(sock->inbuf);
+      silc_socket_free(sock);
       return FALSE;
     }
 
@@ -357,6 +360,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
                      "(%d bytes)", paddedlen + mac_len - sock->inbuf->len));
       SILC_SET_INBUF_PENDING(sock);
       memset(tmp, 0, sizeof(tmp));
+      silc_socket_free(sock);
       return TRUE;
     }
 
@@ -364,10 +368,10 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     if (!silc_packet_check_mac(hmac, sock->inbuf->data, paddedlen,
                               sock->inbuf->data + paddedlen, sequence)) {
       SILC_LOG_WARNING(("Packet MAC check failed %s:%d "
-                       "[%s type %d len %dB seq %d] [%s] proto %d",
+                       "[%s type %d len %dB blen %dB seq %d] [%s] proto %d",
                        sock->hostname, sock->port,
                        silc_get_packet_name(header[3]),
-                       header[3], paddedlen, sequence,
+                       header[3], paddedlen, sock->inbuf->len, sequence,
                        (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
                         sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
                         sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
@@ -375,13 +379,16 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
                        sock->protocol ? sock->protocol->protocol->type : -1));
       memset(tmp, 0, sizeof(tmp));
       silc_buffer_clear(sock->inbuf);
+      silc_socket_free(sock);
       return FALSE;
     }
 
     SILC_UNSET_INBUF_PENDING(sock);
     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
-    if (!parse_ctx)
+    if (!parse_ctx) {
+      silc_socket_free(sock);
       return FALSE;
+    }
     parse_ctx->packet = silc_packet_context_alloc();
     parse_ctx->packet->buffer = silc_buffer_alloc_size(paddedlen);
     parse_ctx->packet->type = (SilcPacketType)header[3];
@@ -432,6 +439,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
        memset(tmp, 0, sizeof(tmp));
        silc_packet_context_free(parse_ctx->packet);
        silc_free(parse_ctx);
+       silc_socket_free(sock);
        return FALSE;
       }
     }
@@ -458,11 +466,21 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     memset(tmp, 0, sizeof(tmp));
   }
 
-  if (cont == FALSE && sock->inbuf->len > 0)
+  /* Don't clear buffer if pending data is in the buffer */
+  if (cont == FALSE && sock->inbuf->len > 0) {
+    silc_socket_free(sock);
     return TRUE;
+  }
+
+  /* Don't clear buffer if QoS data exists in the buffer */
+  if (sock->qos && sock->qos->data_len > 0) {
+    silc_socket_free(sock);
+    return TRUE;
+  }
 
   SILC_LOG_DEBUG(("Clearing inbound buffer"));
   silc_buffer_clear(sock->inbuf);
+  silc_socket_free(sock);
   return TRUE;
 }