Fixed packet queue purging.
[silc.git] / apps / silcd / packet_send.c
index 5cd6168e4ba4c11f72ac20bb4e45ec05e879be5d..a6191b799191098310069d7284be31b42ce18d73 100644 (file)
@@ -78,7 +78,7 @@ void silc_server_packet_send(SilcServer server,
                             SilcPacketType type, 
                             SilcPacketFlags flags,
                             unsigned char *data, 
-                            uint32 data_len,
+                            SilcUInt32 data_len,
                             bool force_send)
 {
   void *dst_id = NULL;
@@ -133,16 +133,17 @@ void silc_server_packet_send_dest(SilcServer server,
                                  void *dst_id,
                                  SilcIdType dst_id_type,
                                  unsigned char *data, 
-                                 uint32 data_len,
+                                 SilcUInt32 data_len,
                                  bool force_send)
 {
   SilcPacketContext packetdata;
+  const SilcBufferStruct packet;
   SilcIDListData idata = (SilcIDListData)sock->user_data;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
-  uint32 sequence = 0;
+  SilcUInt32 sequence = 0;
   unsigned char *dst_id_data = NULL;
-  uint32 dst_id_len = 0;
+  SilcUInt32 dst_id_len = 0;
   int block_len = 0;
 
   /* If disconnecting, ignore the data */
@@ -176,39 +177,30 @@ void silc_server_packet_send_dest(SilcServer server,
   packetdata.dst_id = dst_id_data;
   packetdata.dst_id_len = dst_id_len;
   packetdata.dst_id_type = dst_id_type;
+  data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
+                                           packetdata.src_id_len + 
+                                           packetdata.dst_id_len));
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + dst_id_len;
   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
 
-  /* Prepare outgoing data buffer for packet sending */
-  silc_packet_send_prepare(sock, 
-                          SILC_PACKET_HEADER_LEN +
-                          packetdata.src_id_len + 
-                          packetdata.dst_id_len,
-                          packetdata.padlen,
-                          data_len);
-
-  SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
-
-  packetdata.buffer = sock->outbuf;
-
-  /* Put the data to the buffer */
-  if (data && data_len)
-    silc_buffer_put(sock->outbuf, data, data_len);
-
   /* Create the outgoing packet */
-  silc_packet_assemble(&packetdata, cipher);
+  if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock,
+                            data, data_len, (const SilcBuffer)&packet)) {
+    SILC_LOG_ERROR(("Cannot assemble packet"));
+    goto out;
+  }
 
   /* Encrypt the packet */
-  silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len);
+  silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len);
 
-  SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, 
-                   sock->outbuf->len),
-                  sock->outbuf->data, sock->outbuf->len);
+  SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len),
+                  packet.data, packet.len);
 
   /* Now actually send the packet */
   silc_server_packet_send_real(server, sock, force_send);
 
+ out:
   if (packetdata.src_id)
     silc_free(packetdata.src_id);
   if (packetdata.dst_id)
@@ -232,18 +224,19 @@ void silc_server_packet_send_srcdest(SilcServer server,
                                     void *dst_id,
                                     SilcIdType dst_id_type,
                                     unsigned char *data, 
-                                    uint32 data_len,
+                                    SilcUInt32 data_len,
                                     bool force_send)
 {
   SilcPacketContext packetdata;
+  const SilcBufferStruct packet;
   SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
-  uint32 sequence = 0;
+  SilcUInt32 sequence = 0;
   unsigned char *dst_id_data = NULL;
-  uint32 dst_id_len = 0;
+  SilcUInt32 dst_id_len = 0;
   unsigned char *src_id_data = NULL;
-  uint32 src_id_len = 0;
+  SilcUInt32 src_id_len = 0;
   int block_len = 0;
 
   SILC_LOG_DEBUG(("Sending packet, type %d", type));
@@ -277,39 +270,30 @@ void silc_server_packet_send_srcdest(SilcServer server,
   packetdata.dst_id = dst_id_data;
   packetdata.dst_id_len = dst_id_len;
   packetdata.dst_id_type = dst_id_type;
+  data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
+                                           packetdata.src_id_len + 
+                                           dst_id_len));
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + dst_id_len;
   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
 
-  /* Prepare outgoing data buffer for packet sending */
-  silc_packet_send_prepare(sock, 
-                          SILC_PACKET_HEADER_LEN +
-                          packetdata.src_id_len + 
-                          packetdata.dst_id_len,
-                          packetdata.padlen,
-                          data_len);
-
-  SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
-
-  packetdata.buffer = sock->outbuf;
-
-  /* Put the data to the buffer */
-  if (data && data_len)
-    silc_buffer_put(sock->outbuf, data, data_len);
-
   /* Create the outgoing packet */
-  silc_packet_assemble(&packetdata, cipher);
+  if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock, data,
+                            data_len, (const SilcBuffer)&packet)) {
+    SILC_LOG_ERROR(("Cannot assemble packe"));
+    goto out;
+  }
 
   /* Encrypt the packet */
-  silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len);
+  silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len);
 
-  SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, 
-                   sock->outbuf->len),
-                  sock->outbuf->data, sock->outbuf->len);
+  SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len),
+                   packet.data, packet.len);
 
   /* Now actually send the packet */
   silc_server_packet_send_real(server, sock, force_send);
 
+ out:
   if (packetdata.src_id)
     silc_free(packetdata.src_id);
   if (packetdata.dst_id)
@@ -335,17 +319,23 @@ void silc_server_packet_broadcast(SilcServer server,
      not allowed to send the packet. */
   id = silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type);
   if (id && !SILC_ID_SERVER_COMPARE(id, server->router->id)) {
+    const SilcBufferStruct p;
+
     idata = (SilcIDListData)sock->user_data;
 
     silc_buffer_push(buffer, buffer->data - buffer->head);
-    silc_packet_send_prepare(sock, 0, 0, buffer->len); 
-    silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
+    if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
+                                  (const SilcBuffer)&p)) {
+      SILC_LOG_ERROR(("Cannot send packet"));
+      silc_free(id);
+      return;
+    }
+    silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
     silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
-                       sock->outbuf, sock->outbuf->len);
+                       (SilcBuffer)&p, p.len);
 
     SILC_LOG_HEXDUMP(("Broadcasted packet (%d), len %d", idata->psn_send - 1,
-                     sock->outbuf->len),
-                    sock->outbuf->data, sock->outbuf->len);
+                     p.len), p.data, p.len);
 
     /* Now actually send the packet */
     silc_server_packet_send_real(server, sock, TRUE);
@@ -366,6 +356,7 @@ void silc_server_packet_route(SilcServer server,
                              SilcPacketContext *packet)
 {
   SilcBuffer buffer = packet->buffer;
+  const SilcBufferStruct p;
   SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Routing received packet"));
@@ -373,14 +364,17 @@ void silc_server_packet_route(SilcServer server,
   idata = (SilcIDListData)sock->user_data;
 
   silc_buffer_push(buffer, buffer->data - buffer->head);
-  silc_packet_send_prepare(sock, 0, 0, buffer->len); 
-  silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
+  if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
+                                (const SilcBuffer)&p)) {
+    SILC_LOG_ERROR(("Cannot send packet"));
+    return;
+  }
+  silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
   silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
-                     sock->outbuf, sock->outbuf->len);
+                     (SilcBuffer)&p, p.len);
 
   SILC_LOG_HEXDUMP(("Routed packet (%d), len %d", idata->psn_send - 1, 
-                   sock->outbuf->len),
-                  sock->outbuf->data, sock->outbuf->len);
+                  p.len), p.data, p.len);
 
   /* Now actually send the packet */
   silc_server_packet_send_real(server, sock, TRUE);
@@ -392,18 +386,18 @@ void silc_server_packet_route(SilcServer server,
 
 void silc_server_packet_send_clients(SilcServer server,
                                     SilcClientEntry *clients,
-                                    uint32 clients_count,
+                                    SilcUInt32 clients_count,
                                     SilcPacketType type, 
                                     SilcPacketFlags flags,
                                     bool route,
                                     unsigned char *data, 
-                                    uint32 data_len,
+                                    SilcUInt32 data_len,
                                     bool force_send)
 {
   SilcSocketConnection sock = NULL;
   SilcClientEntry client = NULL;
   SilcServerEntry *routed = NULL;
-  uint32 routed_count = 0;
+  SilcUInt32 routed_count = 0;
   bool gone = FALSE;
   int i, k;
 
@@ -469,17 +463,21 @@ silc_server_packet_send_to_channel_real(SilcServer server,
                                        SilcPacketContext *packet,
                                        SilcCipher cipher,
                                        SilcHmac hmac,
-                                       uint32 sequence,
+                                       SilcUInt32 sequence,
                                        unsigned char *data,
-                                       uint32 data_len,
+                                       SilcUInt32 data_len,
                                        bool channel_message,
                                        bool force_send)
 {
   int block_len;
+  const SilcBufferStruct p;
 
   if (!sock)
     return;
 
+  data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
+                                           packet->src_id_len + 
+                                           packet->dst_id_len));
   packet->truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packet->src_id_len + packet->dst_id_len;
 
@@ -491,32 +489,24 @@ silc_server_packet_send_to_channel_real(SilcServer server,
   else
     packet->padlen = SILC_PACKET_PADLEN(packet->truelen, block_len);
 
-  /* Prepare outgoing data buffer for packet sending */
-  silc_packet_send_prepare(sock, 
-                          SILC_PACKET_HEADER_LEN +
-                          packet->src_id_len + 
-                          packet->dst_id_len,
-                          packet->padlen,
-                          data_len);
-
-  packet->buffer = sock->outbuf;
-
   /* Put the data to buffer, assemble and encrypt the packet. The packet
      is encrypted with normal session key shared with the client, unless
      the `channel_message' is TRUE. */
-  silc_buffer_put(sock->outbuf, data, data_len);
-  silc_packet_assemble(packet, cipher);
+  if (!silc_packet_assemble(packet, NULL, cipher, hmac, sock, data,
+                            data_len, (const SilcBuffer)&p)) {
+    SILC_LOG_ERROR(("Cannot assemble packet"));
+    return;
+  }
+
   if (channel_message)
-    silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf
+    silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p
                        SILC_PACKET_HEADER_LEN + packet->src_id_len + 
                        packet->dst_id_len + packet->padlen);
   else
-    silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, 
-                       sock->outbuf->len);
+    silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, p.len);
     
-  SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence, 
-                   sock->outbuf->len),
-                  sock->outbuf->data, sock->outbuf->len);
+  SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence, p.len),
+                  p.data, p.len);
 
   /* Now actually send the packet */
   silc_server_packet_send_real(server, sock, force_send);
@@ -538,7 +528,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
                                        SilcPacketType type,
                                        bool route,
                                        unsigned char *data,
-                                       uint32 data_len,
+                                       SilcUInt32 data_len,
                                        bool force_send)
 {
   SilcSocketConnection sock = NULL;
@@ -548,7 +538,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
   SilcChannelClientEntry chl;
   SilcHashTableList htl;
   SilcIDListData idata;
-  uint32 routed_count = 0;
+  SilcUInt32 routed_count = 0;
   bool gone = FALSE;
   int k;
 
@@ -649,7 +639,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
     sock = (SilcSocketConnection)client->connection;
     idata = (SilcIDListData)client;
     
-    if (sender && sock == sender)
+    if (!sock || (sender && sock == sender))
       continue;
 
     /* Send the packet */
@@ -661,6 +651,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
                                            force_send);
   }
 
+  silc_hash_table_list_reset(&htl);
   silc_free(routed);
   silc_free(packetdata.src_id);
   silc_free(packetdata.dst_id);
@@ -687,8 +678,8 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
       !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) &&
       channel->channel_key) {
     SilcBuffer chp;
-    uint32 iv_len, i;
-    uint16 dlen, flags;
+    SilcUInt32 iv_len, i;
+    SilcUInt16 dlen, flags;
 
     iv_len = silc_cipher_get_block_len(channel->channel_key);
     if (channel->iv[0] == '\0')
@@ -709,7 +700,7 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
     chp = silc_channel_message_payload_encode(flags, dlen, data + 4,
                                              iv_len, channel->iv,
                                              channel->channel_key,
-                                             channel->hmac);
+                                             channel->hmac, NULL);
     memcpy(data, chp->data, chp->len);
     silc_buffer_free(chp);
   }
@@ -733,7 +724,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
                                         SilcIdType sender_type,
                                         void *sender_entry,
                                         unsigned char *data,
-                                        uint32 data_len,
+                                        SilcUInt32 data_len,
                                         bool force_send)
 {
   bool found = FALSE;
@@ -742,7 +733,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   SilcClientEntry client = NULL;
   SilcServerEntry *routed = NULL;
   SilcChannelClientEntry chl;
-  uint32 routed_count = 0;
+  SilcUInt32 routed_count = 0;
   SilcIDListData idata;
   SilcHashTableList htl;
   bool gone = FALSE;
@@ -874,8 +865,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
        /* If private key mode is not set then decrypt the packet
           and re-encrypt it */
        if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
-         unsigned char *tmp = silc_calloc(data_len, sizeof(*data));
-         memcpy(tmp, data, data_len);
+         unsigned char *tmp = silc_memdup(data, data_len);
 
          /* Decrypt the channel message (we don't check the MAC) */
          if (channel->channel_key &&
@@ -927,7 +917,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
     sock = (SilcSocketConnection)client->connection;
     idata = (SilcIDListData)client;
 
-    if (sender_sock && sock == sender_sock)
+    if (!sock || (sender_sock && sock == sender_sock))
       continue;
 
     SILC_LOG_DEBUG(("Sending packet to client ID(%s) %s (%s)", 
@@ -943,6 +933,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
                                            force_send);
   }
 
+  silc_hash_table_list_reset(&htl);
   silc_free(routed);
   silc_free(packetdata.src_id);
   silc_free(packetdata.dst_id);
@@ -960,7 +951,7 @@ void silc_server_packet_send_local_channel(SilcServer server,
                                           SilcPacketType type,
                                           SilcPacketFlags flags,
                                           unsigned char *data,
-                                          uint32 data_len,
+                                          SilcUInt32 data_len,
                                           bool force_send)
 {
   SilcChannelClientEntry chl;
@@ -981,6 +972,7 @@ void silc_server_packet_send_local_channel(SilcServer server,
                                   force_send);
     }
   }
+  silc_hash_table_list_reset(&htl);
 }
 
 /* Routine used to send (relay, route) private messages to some destination.
@@ -993,39 +985,34 @@ void silc_server_send_private_message(SilcServer server,
                                      SilcSocketConnection dst_sock,
                                      SilcCipher cipher,
                                      SilcHmac hmac,
-                                     uint32 sequence,
+                                     SilcUInt32 sequence,
                                      SilcPacketContext *packet)
 {
   SilcBuffer buffer = packet->buffer;
+  const SilcBufferStruct p;
+
+  silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
+                  + packet->dst_id_len + packet->padlen);
+  if (!silc_packet_send_prepare(dst_sock, 0, 0, buffer->len, hmac,
+                                (const SilcBuffer)&p)) {
+    SILC_LOG_ERROR(("Cannot send packet"));
+    return;
+  }
+  silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
 
   /* Re-encrypt and send if private messge key does not exist */
   if (!(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY)) {
-
-    silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
-                    + packet->dst_id_len + packet->padlen);
-    silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
-    silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
-
     /* Re-encrypt packet */
-    silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, buffer->len);
-
-    /* Send the packet */
-    silc_server_packet_send_real(server, dst_sock, FALSE);
-
+    silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, buffer->len);
   } else {
     /* Key exist so encrypt just header and send it */
-    silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
-                    + packet->dst_id_len + packet->padlen);
-    silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
-    silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
-
-    /* Encrypt header */
-    silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, 
+    silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, 
                        SILC_PACKET_HEADER_LEN + packet->src_id_len + 
                        packet->dst_id_len + packet->padlen);
-
-    silc_server_packet_send_real(server, dst_sock, FALSE);
   }
+
+  /* Send the packet */
+  silc_server_packet_send_real(server, dst_sock, FALSE);
 }
 
 /* Sends current motd to client */
@@ -1033,13 +1020,14 @@ void silc_server_send_private_message(SilcServer server,
 void silc_server_send_motd(SilcServer server,
                           SilcSocketConnection sock)
 {
-  char *motd;
-  uint32 motd_len;
+  char *motd, *motd_file = NULL;
+  SilcUInt32 motd_len;
 
-  if (server->config && server->config->motd && 
-      server->config->motd->motd_file) {
+  if (server->config)
+    motd_file = server->config->server_info->motd_file;
 
-    motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
+  if (motd_file) {
+    motd = silc_file_readfile(motd_file, &motd_len);
     if (!motd)
       return;
 
@@ -1077,7 +1065,7 @@ void silc_server_send_notify(SilcServer server,
                             SilcSocketConnection sock,
                             bool broadcast,
                             SilcNotifyType type,
-                            uint32 argc, ...)
+                            SilcUInt32 argc, ...)
 {
   va_list ap;
   SilcBuffer packet;
@@ -1107,7 +1095,7 @@ void silc_server_send_notify_args(SilcServer server,
                                  SilcSocketConnection sock,
                                  bool broadcast,
                                  SilcNotifyType type,
-                                 uint32 argc,
+                                 SilcUInt32 argc,
                                  SilcBuffer args)
 {
   SilcBuffer packet;
@@ -1207,7 +1195,7 @@ void silc_server_send_notify_cmode(SilcServer server,
                                   SilcSocketConnection sock,
                                   bool broadcast,
                                   SilcChannelEntry channel,
-                                  uint32 mode_mask,
+                                  SilcUInt32 mode_mask,
                                   void *id, SilcIdType id_type,
                                   char *cipher, char *hmac,
                                   char *passphrase)
@@ -1237,7 +1225,7 @@ void silc_server_send_notify_cumode(SilcServer server,
                                    SilcSocketConnection sock,
                                    bool broadcast,
                                    SilcChannelEntry channel,
-                                   uint32 mode_mask,
+                                   SilcUInt32 mode_mask,
                                    void *id, SilcIdType id_type,
                                    SilcClientID *target)
 {
@@ -1358,7 +1346,7 @@ void silc_server_send_notify_umode(SilcServer server,
                                   SilcSocketConnection sock,
                                   bool broadcast,
                                   SilcClientID *client_id,
-                                  uint32 mode_mask)
+                                  SilcUInt32 mode_mask)
 {
   SilcBuffer idp;
   unsigned char mode[4];
@@ -1429,7 +1417,7 @@ void silc_server_send_notify_dest(SilcServer server,
                                  void *dest_id,
                                  SilcIdType dest_id_type,
                                  SilcNotifyType type,
-                                 uint32 argc, ...)
+                                 SilcUInt32 argc, ...)
 {
   va_list ap;
   SilcBuffer packet;
@@ -1457,7 +1445,7 @@ void silc_server_send_notify_to_channel(SilcServer server,
                                        SilcChannelEntry channel,
                                        bool route_notify,
                                        SilcNotifyType type,
-                                       uint32 argc, ...)
+                                       SilcUInt32 argc, ...)
 {
   va_list ap;
   SilcBuffer packet;
@@ -1483,23 +1471,23 @@ void silc_server_send_notify_on_channels(SilcServer server,
                                         SilcClientEntry sender,
                                         SilcClientEntry client,
                                         SilcNotifyType type,
-                                        uint32 argc, ...)
+                                        SilcUInt32 argc, ...)
 {
   int k;
   SilcSocketConnection sock = NULL;
   SilcPacketContext packetdata;
   SilcClientEntry c;
   SilcClientEntry *sent_clients = NULL;
-  uint32 sent_clients_count = 0;
+  SilcUInt32 sent_clients_count = 0;
   SilcServerEntry *routed = NULL;
-  uint32 routed_count = 0;
+  SilcUInt32 routed_count = 0;
   SilcHashTableList htl, htl2;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl, chl2;
   SilcIDListData idata;
   SilcBuffer packet;
   unsigned char *data;
-  uint32 data_len;
+  SilcUInt32 data_len;
   bool force_send = FALSE;
   va_list ap;
 
@@ -1593,6 +1581,9 @@ void silc_server_send_notify_on_channels(SilcServer server,
        sock = (SilcSocketConnection)c->connection;
        idata = (SilcIDListData)c;
        
+        if (!sock)
+          continue;
+
        packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_len = silc_id_get_len(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_type = SILC_ID_CLIENT;
@@ -1613,8 +1604,10 @@ void silc_server_send_notify_on_channels(SilcServer server,
        sent_clients[sent_clients_count++] = c;
       }
     }
+    silc_hash_table_list_reset(&htl2);
   }
 
+  silc_hash_table_list_reset(&htl);
   silc_free(routed);
   silc_free(sent_clients);
   silc_free(packetdata.src_id);
@@ -1632,7 +1625,7 @@ void silc_server_send_new_id(SilcServer server,
                             SilcSocketConnection sock,
                             bool broadcast,
                             void *id, SilcIdType id_type, 
-                            uint32 id_len)
+                            SilcUInt32 id_len)
 {
   SilcBuffer idp;
 
@@ -1654,21 +1647,20 @@ void silc_server_send_new_id(SilcServer server,
 }
 
 /* Send New Channel Payload to notify about newly created channel in the
-   SILC network. Normal server nevers sends this packet. Router uses this
-   to notify other routers in the network about new channel. This packet
-   is broadcasted. */
+   SILC network. Router uses this to notify other routers in the network 
+   about new channel. This packet is broadcasted by router. */
 
 void silc_server_send_new_channel(SilcServer server,
                                  SilcSocketConnection sock,
                                  bool broadcast,
                                  char *channel_name,
                                  void *channel_id, 
-                                 uint32 channel_id_len,
-                                 uint32 mode)
+                                 SilcUInt32 channel_id_len,
+                                 SilcUInt32 mode)
 {
   SilcBuffer packet;
   unsigned char *cid;
-  uint32 name_len = strlen(channel_name);
+  SilcUInt32 name_len = strlen(channel_name);
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -1686,7 +1678,8 @@ void silc_server_send_new_channel(SilcServer server,
 
   /* Send to backup routers if this is being broadcasted to primary
      router. */
-  if (server->router && server->router->connection &&
+  if (server->server_type == SILC_ROUTER &&
+      server->router && server->router->connection &&
       sock == server->router->connection && broadcast)
     silc_server_backup_send(server, NULL, SILC_PACKET_NEW_CHANNEL, 0,
                            packet->data, packet->len, FALSE, TRUE);
@@ -1711,7 +1704,7 @@ void silc_server_send_channel_key(SilcServer server,
 {
   SilcBuffer packet;
   unsigned char *chid;
-  uint32 tmp_len;
+  SilcUInt32 tmp_len;
  
   SILC_LOG_DEBUG(("Sending key to channel %s", channel->channel_name));
  
@@ -1740,8 +1733,8 @@ void silc_server_send_channel_key(SilcServer server,
 void silc_server_send_command(SilcServer server, 
                              SilcSocketConnection sock,
                              SilcCommand command, 
-                             uint16 ident,
-                             uint32 argc, ...)
+                             SilcUInt16 ident,
+                             SilcUInt32 argc, ...)
 {
   SilcBuffer packet;
   va_list ap;
@@ -1762,8 +1755,8 @@ void silc_server_send_command_reply(SilcServer server,
                                    SilcSocketConnection sock,
                                    SilcCommand command, 
                                    SilcCommandStatus status,
-                                   uint16 ident,
-                                   uint32 argc, ...)
+                                   SilcUInt16 ident,
+                                   SilcUInt32 argc, ...)
 {
   SilcBuffer packet;
   va_list ap;
@@ -1787,8 +1780,8 @@ void silc_server_send_dest_command_reply(SilcServer server,
                                         SilcIdType dst_id_type,
                                         SilcCommand command, 
                                         SilcCommandStatus status,
-                                        uint16 ident,
-                                        uint32 argc, ...)
+                                        SilcUInt16 ident,
+                                        SilcUInt32 argc, ...)
 {
   SilcBuffer packet;
   va_list ap;
@@ -1820,18 +1813,23 @@ void silc_server_relay_packet(SilcServer server,
                              SilcSocketConnection dst_sock,
                              SilcCipher cipher,
                              SilcHmac hmac,
-                             uint32 sequence,
+                             SilcUInt32 sequence,
                              SilcPacketContext *packet,
                              bool force_send)
 {
+  const SilcBufferStruct p;
+
   silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
                   + packet->dst_id_len + packet->padlen);
-
-  silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len);
-  silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len);
+  if (!silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len, hmac,
+                                (const SilcBuffer)&p)) {
+    SILC_LOG_ERROR(("Cannot send packet"));
+    return;
+  }
+  silc_buffer_put((SilcBuffer)&p, packet->buffer->data, packet->buffer->len);
   
   /* Re-encrypt packet */
-  silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, 
+  silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p,
                      packet->buffer->len);
   
   /* Send the packet */
@@ -1845,7 +1843,7 @@ void silc_server_relay_packet(SilcServer server,
 
 void silc_server_send_connection_auth_request(SilcServer server,
                                              SilcSocketConnection sock,
-                                             uint16 conn_type,
+                                             SilcUInt16 conn_type,
                                              SilcAuthMethod auth_meth)
 {
   SilcBuffer packet;
@@ -1872,12 +1870,7 @@ void silc_server_packet_queue_purge(SilcServer server,
   if (sock && SILC_IS_OUTBUF_PENDING(sock) && 
       (SILC_IS_DISCONNECTED(sock) == FALSE)) {
     server->stat.packets_sent++;
-
-    if (sock->outbuf->data - sock->outbuf->head)
-      silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
-
     silc_packet_send(sock, TRUE);
-
     SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
     SILC_UNSET_OUTBUF_PENDING(sock);
     silc_buffer_clear(sock->outbuf);