Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch silc.server.1.1.13
authorPekka Riikonen <priikone@silcnet.org>
Wed, 24 Sep 2008 15:18:30 +0000 (18:18 +0300)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 24 Sep 2008 15:18:30 +0000 (18:18 +0300)
Signed-off-by: Pekka Riikonen <priikone@silcnet.org>
1  2 
apps/silcd/command.c
lib/silcclient/client.h
lib/silcclient/client_entry.c
lib/silccore/silcpacket.c

diff --combined apps/silcd/command.c
index f35969ecf8968c3377595a04bd8fe7b84e63c50e,d8d105c535a76a72de9518fe9c1853fe17c48765..2bd8198ebcfd0e2583b84098c1063bfe777c8cdd
@@@ -1472,12 -1472,19 +1472,19 @@@ SILC_SERVER_CMD_FUNC(kill
  
      /* Do normal signoff for the destination client */
      sock = remote_client->connection;
+     if (sock)
+       silc_packet_stream_ref(sock);
      silc_server_remove_from_channels(server, NULL, remote_client,
                                     TRUE, (char *)"Killed", TRUE, TRUE);
      silc_server_free_sock_user_data(server, sock, comment ? comment :
                                    (unsigned char *)"Killed");
-     if (sock)
+     if (sock) {
+       silc_packet_set_context(sock, NULL);
        silc_server_close_connection(server, sock);
+       silc_packet_stream_unref(sock);
+     }
    } else {
      /* Router operator killing */
  
@@@ -1557,13 -1564,12 +1564,13 @@@ SILC_SERVER_CMD_FUNC(info
      char info_string[256];
  
      memset(info_string, 0, sizeof(info_string));
 -    snprintf(info_string, sizeof(info_string),
 -           "location: %s server: %s admin: %s <%s>",
 -           server->config->server_info->location,
 -           server->config->server_info->server_type,
 -           server->config->server_info->admin,
 -           server->config->server_info->email);
 +    silc_snprintf(info_string, sizeof(info_string),
 +                "location: %s server: %s admin: %s <%s> version: %s",
 +                server->config->server_info->location,
 +                server->config->server_info->server_type,
 +                server->config->server_info->admin,
 +                server->config->server_info->email,
 +                silc_dist_version);
  
      server_info = info_string;
      entry = server->id_entry;
@@@ -2824,7 -2830,7 +2831,7 @@@ SILC_SERVER_CMD_FUNC(umode
    SilcServer server = cmd->server;
    SilcClientEntry client = silc_packet_get_context(cmd->sock);
    unsigned char *tmp_mask, m[4];
 -  SilcUInt32 mask = 0;
 +  SilcUInt32 mask = 0, tmp_len;
    SilcUInt16 ident = silc_command_get_ident(cmd->payload);
    SilcBool set_mask = FALSE;
  
    SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
  
    /* Get the client's mode mask */
 -  tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
 -  if (tmp_mask) {
 +  tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
 +  if (tmp_mask && tmp_len == 4) {
      SILC_GET32_MSB(mask, tmp_mask);
      set_mask = TRUE;
    }
@@@ -2948,7 -2954,7 +2955,7 @@@ SILC_SERVER_CMD_FUNC(cmode
  
    /* Get the channel mode mask */
    tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
 -  if (tmp_mask) {
 +  if (tmp_mask && tmp_len == 4) {
      SILC_GET32_MSB(mode_mask, tmp_mask);
      set_mask = TRUE;
    }
diff --combined lib/silcclient/client.h
index ac1116d28289951ced21ef6933114ecb7f5cda68,ebe41fe903f752ee261e14cd18edd51e7042adad..d66808dcef168e06473e7168104b18f97430ce43
@@@ -53,14 -53,16 +53,17 @@@ typedef struct SilcClientEntryInternalS
    SilcUInt32 key_len;         /* Key data length */
    SilcClientKeyAgreement ke;  /* Current key agreement context or NULL */
  
++  SilcAtomic32 refcnt;                /* Reference counter */
++  SilcAtomic32 deleted;               /* Flag indicating whether the client object is
++                                 already scheduled for deletion */
++  SilcUInt16 resolve_cmd_ident;       /* Command identifier when resolving */
++
    /* Flags */
    unsigned int valid       : 1;       /* FALSE if this entry is not valid.  Entry
                                   without nickname is not valid. */
    unsigned int generated   : 1; /* TRUE if library generated `key' */
    unsigned int prv_resp    : 1; /* TRUE if we are responder when using
                                   private message keys. */
--  SilcUInt16 resolve_cmd_ident;       /* Command identifier when resolving */
-   SilcAtomic8 refcnt;         /* Reference counter */
 -  SilcAtomic32 refcnt;                /* Reference counter */
 -  SilcAtomic32 deleted;     /* Flag indicating whether the client object is
 -                                                                         already scheduled for deletion.*/
  } SilcClientEntryInternal;
  
  /* Internal channel entry context */
@@@ -81,20 -83,22 +84,23 @@@ typedef struct SilcChannelEntryInternal
    SilcHmac hmac;                           /* Current HMAC */
    unsigned char iv[SILC_CIPHER_MAX_IV_SIZE]; /* Current IV */
  
++  SilcAtomic32 refcnt;                             /* Reference counter */
++  SilcAtomic32 deleted;                      /* Flag indicating whether the
++                                              channel object is already
++                                              scheduled for deletion */
    SilcUInt16 resolve_cmd_ident;                    /* Channel information resolving
                                                identifier. This is used when
                                                resolving users, and other
                                                stuff that relates to the
                                                channel. Not used for the
                                                channel resolving itself. */
-   SilcAtomic16 refcnt;                             /* Reference counter */
 -  SilcAtomic32 refcnt;                             /* Reference counter */
 -  SilcAtomic32 deleted;     /* Flag indicating whether the channel object is
 -                                                                         already scheduled for deletion.*/
  } SilcChannelEntryInternal;
  
  /* Internal server entry context */
  typedef struct SilcServerEntryInternalStruct {
    SilcRwLock lock;                         /* Read/write lock */
    SilcUInt16 resolve_cmd_ident;                    /* Resolving identifier */
-   SilcAtomic8 refcnt;                      /* Reference counter */
+   SilcAtomic32 refcnt;                             /* Reference counter */
  } SilcServerEntryInternal;
  
  #endif /* CLIENT_H */
index 0933c3d4d8bad4b48ac0025b2564de8034b4ada2,bdcdd1cabe47843af73bb0195e3ba335b477b5b1..4664dbaa75f770446b457b8b7d830b67cab2d524
@@@ -791,7 -791,8 +791,8 @@@ SilcClientEntry silc_client_add_client(
      return NULL;
  
    silc_rwlock_alloc(&client_entry->internal.lock);
-   silc_atomic_init8(&client_entry->internal.refcnt, 0);
+   silc_atomic_init32(&client_entry->internal.refcnt, 0);
+   silc_atomic_init32(&client_entry->internal.deleted, 1);
    client_entry->id = *id;
    client_entry->mode = mode;
    client_entry->realname = userinfo ? strdup(userinfo) : NULL;
@@@ -995,7 -996,8 +996,8 @@@ void silc_client_del_client_entry(SilcC
    silc_client_ftp_session_free_client(client, client_entry);
    if (client_entry->internal.ke)
      silc_client_abort_key_agreement(client, conn, client_entry);
-   silc_atomic_uninit8(&client_entry->internal.refcnt);
+   silc_atomic_uninit32(&client_entry->internal.deleted);
+   silc_atomic_uninit32(&client_entry->internal.refcnt);
    silc_rwlock_free(client_entry->internal.lock);
    silc_free(client_entry);
  }
  SilcBool silc_client_del_client(SilcClient client, SilcClientConnection conn,
                                SilcClientEntry client_entry)
  {
-   SilcBool ret;
    if (!client_entry)
      return FALSE;
  
-   if (silc_atomic_sub_int8(&client_entry->internal.refcnt, 1) > 0)
-     return FALSE;
-   SILC_LOG_DEBUG(("Deleting client %p", client_entry));
-   silc_mutex_lock(conn->internal->lock);
-   ret = silc_idcache_del_by_context(conn->internal->client_cache,
-                                   client_entry, NULL);
-   silc_mutex_unlock(conn->internal->lock);
-   if (ret) {
-     /* Remove from channels */
-     silc_client_remove_from_channels(client, conn, client_entry);
 -  if (silc_atomic_sub_int32(&client_entry->internal.deleted, 1) != 0)
 -  {
 -        SILC_LOG_DEBUG(("** WARNING ** Deleting a client twice %p", client_entry));
 -//      asm("int3");
 -        return FALSE;
++  SILC_LOG_DEBUG(("Marking client entry %p deleted"));
 +
-     /* Free the client entry data */
-     silc_client_del_client_entry(client, conn, client_entry);
++  if (silc_atomic_sub_int32(&client_entry->internal.deleted, 1) != 0) {
++    SILC_LOG_DEBUG(("Client entry %p already marked deleted"));
++    return FALSE;
    }
  
-   return ret;
+   silc_client_unref_client(client, conn, client_entry);
+   return TRUE;
 -
  }
  
  /* Internal routine used to find client by ID and if not found this creates
@@@ -1072,10 -1063,10 +1062,10 @@@ SilcClientEntry silc_client_ref_client(
                                       SilcClientConnection conn,
                                       SilcClientEntry client_entry)
  {
-   silc_atomic_add_int8(&client_entry->internal.refcnt, 1);
+   silc_atomic_add_int32(&client_entry->internal.refcnt, 1);
    SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
-                 silc_atomic_get_int8(&client_entry->internal.refcnt) - 1,
-                 silc_atomic_get_int8(&client_entry->internal.refcnt)));
+                 silc_atomic_get_int32(&client_entry->internal.refcnt) - 1,
+                 silc_atomic_get_int32(&client_entry->internal.refcnt)));
    return client_entry;
  }
  
  void silc_client_unref_client(SilcClient client, SilcClientConnection conn,
                              SilcClientEntry client_entry)
  {
--  if (client_entry) {
-     SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
-                   silc_atomic_get_int8(&client_entry->internal.refcnt),
-                   silc_atomic_get_int8(&client_entry->internal.refcnt) - 1));
-     silc_client_del_client(client, conn, client_entry);
 -       SilcBool ret;
++  SilcBool ret;
 -    SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
 -                  silc_atomic_get_int32(&client_entry->internal.refcnt),
 -                  silc_atomic_get_int32(&client_entry->internal.refcnt) - 1));
++  if (!client_entry)
++    return;
 -       if (silc_atomic_sub_int32(&client_entry->internal.refcnt, 1) > 0)
 -              return;
 -       
 -    SILC_LOG_DEBUG(("Deleting client %p (%d)", client_entry,
 -                       silc_atomic_get_int32(&client_entry->internal.deleted)));
++  SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
++                silc_atomic_get_int32(&client_entry->internal.refcnt),
++                silc_atomic_get_int32(&client_entry->internal.refcnt) - 1));
 -    silc_mutex_lock(conn->internal->lock);
 -    ret = silc_idcache_del_by_context(conn->internal->client_cache,
 -                                    client_entry, NULL);
 -    silc_mutex_unlock(conn->internal->lock);
++  if (silc_atomic_sub_int32(&client_entry->internal.refcnt, 1) > 0)
++    return;
 -    if (ret) {
 -      /* Remove from channels */
 -      silc_client_remove_from_channels(client, conn, client_entry);
++  SILC_LOG_DEBUG(("Deleting client %p (%d)", client_entry,
++                silc_atomic_get_int32(&client_entry->internal.deleted)));
 -      /* Free the client entry data */
 -      silc_client_del_client_entry(client, conn, client_entry);
 -    }
++  silc_mutex_lock(conn->internal->lock);
++  ret = silc_idcache_del_by_context(conn->internal->client_cache,
++                                  client_entry, NULL);
++  silc_mutex_unlock(conn->internal->lock);
++
++  if (ret) {
++    /* Remove from channels */
++    silc_client_remove_from_channels(client, conn, client_entry);
++
++    /* Free the client entry data */
++    silc_client_del_client_entry(client, conn, client_entry);
    }
  }
  
@@@ -1626,7 -1637,8 +1637,8 @@@ SilcChannelEntry silc_client_add_channe
      return NULL;
  
    silc_rwlock_alloc(&channel->internal.lock);
-   silc_atomic_init16(&channel->internal.refcnt, 0);
+   silc_atomic_init32(&channel->internal.refcnt, 0);
+   silc_atomic_init32(&channel->internal.deleted, 1);
    channel->id = *channel_id;
    channel->mode = mode;
  
  
    if (!channel->channel_name) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel);
      return NULL;
    }
                                             NULL, NULL, NULL, TRUE);
    if (!channel->user_list) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel->channel_name);
      silc_free(channel);
      return NULL;
                                          SILC_STRING_UTF8, 256, NULL);
    if (!channel_namec) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel->channel_name);
      silc_hash_table_free(channel->user_list);
      silc_free(channel);
    if (!silc_idcache_add(conn->internal->channel_cache, channel_namec,
                        &channel->id, channel)) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel_namec);
      silc_free(channel->channel_name);
      silc_hash_table_free(channel->user_list);
  SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn,
                                 SilcChannelEntry channel)
  {
-   SilcIDCacheEntry id_cache;
-   SilcBool ret = TRUE;
-   SilcCipher key;
-   SilcHmac hmac;
-   char *namec;
    if (!channel)
      return FALSE;
  
-   if (silc_atomic_sub_int16(&channel->internal.refcnt, 1) > 0)
-     return FALSE;
-   SILC_LOG_DEBUG(("Deleting channel %p", channel));
 -  if (silc_atomic_sub_int32(&channel->internal.deleted, 1) > 0)
 -  {
 -    SILC_LOG_DEBUG(("** WARNING ** Deleting a channel twice %p", channel));
 -//  asm("int3");
++  SILC_LOG_DEBUG(("Marking channel entry %p deleted"));
 +
-   silc_mutex_lock(conn->internal->lock);
-   if (silc_idcache_find_by_context(conn->internal->channel_cache, channel,
-                                  &id_cache)) {
-     namec = id_cache->name;
-     ret = silc_idcache_del_by_context(conn->internal->channel_cache,
-                                     channel, NULL);
-     silc_free(namec);
-   }
-   silc_mutex_unlock(conn->internal->lock);
-   if (!ret)
++  if (silc_atomic_sub_int32(&channel->internal.deleted, 1) != 0) {
++    SILC_LOG_DEBUG(("Channel entry %p already marked deleted"));
      return FALSE;
-   silc_client_empty_channel(client, conn, channel);
-   silc_client_del_channel_private_keys(client, conn, channel);
-   silc_hash_table_free(channel->user_list);
-   silc_free(channel->channel_name);
-   silc_free(channel->topic);
-   if (channel->founder_key)
-     silc_pkcs_public_key_free(channel->founder_key);
-   if (channel->internal.send_key)
-     silc_cipher_free(channel->internal.send_key);
-   if (channel->internal.receive_key)
-     silc_cipher_free(channel->internal.receive_key);
-   if (channel->internal.hmac)
-     silc_hmac_free(channel->internal.hmac);
-   if (channel->internal.old_channel_keys) {
-     silc_dlist_start(channel->internal.old_channel_keys);
-     while ((key = silc_dlist_get(channel->internal.old_channel_keys)))
-       silc_cipher_free(key);
-     silc_dlist_uninit(channel->internal.old_channel_keys);
    }
-   if (channel->internal.old_hmacs) {
-     silc_dlist_start(channel->internal.old_hmacs);
-     while ((hmac = silc_dlist_get(channel->internal.old_hmacs)))
-       silc_hmac_free(hmac);
-     silc_dlist_uninit(channel->internal.old_hmacs);
-   }
-   if (channel->channel_pubkeys)
-     silc_argument_list_free(channel->channel_pubkeys,
-                           SILC_ARGUMENT_PUBLIC_KEY);
-   silc_atomic_uninit16(&channel->internal.refcnt);
-   silc_rwlock_free(channel->internal.lock);
-   silc_schedule_task_del_by_context(conn->client->schedule, channel);
-   silc_free(channel);
  
-   return ret;
+   silc_client_unref_channel(client, conn, channel);
+   return TRUE;
  }
  
  /* Replaces the channel ID of the `channel' to `new_id'. Returns FALSE
@@@ -1806,10 -1769,10 +1769,10 @@@ SilcChannelEntry silc_client_ref_channe
                                         SilcClientConnection conn,
                                         SilcChannelEntry channel_entry)
  {
-   silc_atomic_add_int16(&channel_entry->internal.refcnt, 1);
+   silc_atomic_add_int32(&channel_entry->internal.refcnt, 1);
    SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry,
-                 silc_atomic_get_int16(&channel_entry->internal.refcnt) - 1,
-                 silc_atomic_get_int16(&channel_entry->internal.refcnt)));
+                 silc_atomic_get_int32(&channel_entry->internal.refcnt) - 1,
+                 silc_atomic_get_int32(&channel_entry->internal.refcnt)));
    return channel_entry;
  }
  
  void silc_client_unref_channel(SilcClient client, SilcClientConnection conn,
                               SilcChannelEntry channel_entry)
  {
--  if (channel_entry) {
-     SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry,
-                   silc_atomic_get_int16(&channel_entry->internal.refcnt),
-                   silc_atomic_get_int16(&channel_entry->internal.refcnt)
-                   - 1));
-     silc_client_del_channel(client, conn, channel_entry);
 -    SilcIDCacheEntry id_cache;
 -    SilcBool ret = TRUE;
 -    SilcCipher key;
 -    SilcHmac hmac;
 -    char *namec;
++  SilcIDCacheEntry id_cache;
++  SilcBool ret = TRUE;
++  SilcCipher key;
++  SilcHmac hmac;
++  char *namec;
 -    SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry,
 -                  silc_atomic_get_int32(&channel_entry->internal.refcnt),
 -                  silc_atomic_get_int32(&channel_entry->internal.refcnt)
 -                  - 1));
++  if (!channel_entry)
++    return;
 -       if (silc_atomic_sub_int32(&channel_entry->internal.refcnt, 1) > 0)
 -               return;
++  SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry,
++                silc_atomic_get_int32(&channel_entry->internal.refcnt),
++                silc_atomic_get_int32(&channel_entry->internal.refcnt)
++                - 1));
 -       SILC_LOG_DEBUG(("Deleting channel %p", channel_entry));
++  if (silc_atomic_sub_int32(&channel_entry->internal.refcnt, 1) > 0)
++    return;
 -    silc_mutex_lock(conn->internal->lock);
 -    if (silc_idcache_find_by_context(conn->internal->channel_cache, channel_entry,
++  SILC_LOG_DEBUG(("Deleting channel %p", channel_entry));
++
++  silc_mutex_lock(conn->internal->lock);
++  if (silc_idcache_find_by_context(conn->internal->channel_cache, channel_entry,
+                                  &id_cache)) {
 -      namec = id_cache->name;
 -      ret = silc_idcache_del_by_context(conn->internal->channel_cache,
++    namec = id_cache->name;
++    ret = silc_idcache_del_by_context(conn->internal->channel_cache,
+                                     channel_entry, NULL);
 -      silc_free(namec);
 -    }
 -    silc_mutex_unlock(conn->internal->lock);
++    silc_free(namec);
 +  }
++  silc_mutex_unlock(conn->internal->lock);
 -    if (!ret)
 -      return;
++  if (!ret)
++    return;
 -    silc_client_empty_channel(client, conn, channel_entry);
 -    silc_client_del_channel_private_keys(client, conn, channel_entry);
 -    silc_hash_table_free(channel_entry->user_list);
 -    silc_free(channel_entry->channel_name);
 -    silc_free(channel_entry->topic);
 -    if (channel_entry->founder_key)
 -      silc_pkcs_public_key_free(channel_entry->founder_key);
 -    if (channel_entry->internal.send_key)
 -      silc_cipher_free(channel_entry->internal.send_key);
 -    if (channel_entry->internal.receive_key)
 -      silc_cipher_free(channel_entry->internal.receive_key);
 -    if (channel_entry->internal.hmac)
 -      silc_hmac_free(channel_entry->internal.hmac);
 -    if (channel_entry->internal.old_channel_keys) {
 -      silc_dlist_start(channel_entry->internal.old_channel_keys);
 -      while ((key = silc_dlist_get(channel_entry->internal.old_channel_keys)))
 -        silc_cipher_free(key);
 -      silc_dlist_uninit(channel_entry->internal.old_channel_keys);
 -    }
 -    if (channel_entry->internal.old_hmacs) {
 -      silc_dlist_start(channel_entry->internal.old_hmacs);
 -      while ((hmac = silc_dlist_get(channel_entry->internal.old_hmacs)))
 -        silc_hmac_free(hmac);
 -      silc_dlist_uninit(channel_entry->internal.old_hmacs);
 -    }
 -    if (channel_entry->channel_pubkeys)
 -      silc_argument_list_free(channel_entry->channel_pubkeys,
++  silc_client_empty_channel(client, conn, channel_entry);
++  silc_client_del_channel_private_keys(client, conn, channel_entry);
++  silc_hash_table_free(channel_entry->user_list);
++  silc_free(channel_entry->channel_name);
++  silc_free(channel_entry->topic);
++  if (channel_entry->founder_key)
++    silc_pkcs_public_key_free(channel_entry->founder_key);
++  if (channel_entry->internal.send_key)
++    silc_cipher_free(channel_entry->internal.send_key);
++  if (channel_entry->internal.receive_key)
++    silc_cipher_free(channel_entry->internal.receive_key);
++  if (channel_entry->internal.hmac)
++    silc_hmac_free(channel_entry->internal.hmac);
++  if (channel_entry->internal.old_channel_keys) {
++    silc_dlist_start(channel_entry->internal.old_channel_keys);
++    while ((key = silc_dlist_get(channel_entry->internal.old_channel_keys)))
++      silc_cipher_free(key);
++    silc_dlist_uninit(channel_entry->internal.old_channel_keys);
++  }
++  if (channel_entry->internal.old_hmacs) {
++    silc_dlist_start(channel_entry->internal.old_hmacs);
++    while ((hmac = silc_dlist_get(channel_entry->internal.old_hmacs)))
++      silc_hmac_free(hmac);
++    silc_dlist_uninit(channel_entry->internal.old_hmacs);
++  }
++  if (channel_entry->channel_pubkeys)
++    silc_argument_list_free(channel_entry->channel_pubkeys,
+                           SILC_ARGUMENT_PUBLIC_KEY);
 -    silc_atomic_uninit32(&channel_entry->internal.deleted);
 -    silc_atomic_uninit32(&channel_entry->internal.refcnt);
 -    silc_rwlock_free(channel_entry->internal.lock);
 -    silc_schedule_task_del_by_context(conn->client->schedule, channel_entry);
 -    silc_free(channel_entry);
 -  }
++  silc_atomic_uninit32(&channel_entry->internal.deleted);
++  silc_atomic_uninit32(&channel_entry->internal.refcnt);
++  silc_rwlock_free(channel_entry->internal.lock);
++  silc_schedule_task_del_by_context(conn->client->schedule, channel_entry);
++  silc_free(channel_entry);
  }
  
  /* Free channel entry list */
@@@ -2059,7 -2079,7 +2080,7 @@@ SilcServerEntry silc_client_add_server(
      return NULL;
  
    silc_rwlock_alloc(&server_entry->internal.lock);
-   silc_atomic_init8(&server_entry->internal.refcnt, 0);
+   silc_atomic_init32(&server_entry->internal.refcnt, 0);
    server_entry->id = *server_id;
    if (server_name)
      server_entry->server_name = strdup(server_name);
@@@ -2111,7 -2131,7 +2132,7 @@@ SilcBool silc_client_del_server(SilcCli
    if (!server)
      return FALSE;
  
-   if (silc_atomic_sub_int8(&server->internal.refcnt, 1) > 0)
+   if (silc_atomic_sub_int32(&server->internal.refcnt, 1) > 0)
      return FALSE;
  
    SILC_LOG_DEBUG(("Deleting server %p", server));
    silc_free(server->server_info);
    if (server->public_key)
      silc_pkcs_public_key_free(server->public_key);
-   silc_atomic_uninit8(&server->internal.refcnt);
+   silc_atomic_uninit32(&server->internal.refcnt);
    silc_rwlock_free(server->internal.lock);
    silc_free(server);
  
@@@ -2198,10 -2218,10 +2219,10 @@@ SilcServerEntry silc_client_ref_server(
                                       SilcClientConnection conn,
                                       SilcServerEntry server_entry)
  {
-   silc_atomic_add_int8(&server_entry->internal.refcnt, 1);
+   silc_atomic_add_int32(&server_entry->internal.refcnt, 1);
    SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry,
-                 silc_atomic_get_int8(&server_entry->internal.refcnt) - 1,
-                 silc_atomic_get_int8(&server_entry->internal.refcnt)));
+                 silc_atomic_get_int32(&server_entry->internal.refcnt) - 1,
+                 silc_atomic_get_int32(&server_entry->internal.refcnt)));
    return server_entry;
  }
  
@@@ -2212,8 -2232,8 +2233,8 @@@ void silc_client_unref_server(SilcClien
  {
    if (server_entry) {
      SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry,
-                   silc_atomic_get_int8(&server_entry->internal.refcnt),
-                   silc_atomic_get_int8(&server_entry->internal.refcnt)
+                   silc_atomic_get_int32(&server_entry->internal.refcnt),
+                   silc_atomic_get_int32(&server_entry->internal.refcnt)
                    - 1));
      silc_client_del_server(client, conn, server_entry);
    }
index 2c01e6dd65fb1886d7723e83b081dff1a82e54e0,85d8b4e635dd73e24c585ff6f3d7f91e6bb48c85..f552ca6d1741aebf31648e1c694d34c302792ac3
@@@ -40,7 -40,7 +40,7 @@@ struct SilcPacketEngineStruct 
    SilcMutex lock;                      /* Engine lock */
    SilcRng rng;                                 /* RNG for engine */
    SilcHashTable contexts;              /* Per scheduler contexts */
 -  SilcPacketCallbacks *callbacks;      /* Packet callbacks */
 +  const SilcPacketCallbacks *callbacks;        /* Packet callbacks */
    void *callback_context;              /* Context for callbacks */
    SilcList streams;                    /* All streams in engine */
    SilcList packet_pool;                        /* Free list for received packets */
@@@ -51,7 -51,7 +51,7 @@@
  /* Packet processor context */
  typedef struct SilcPacketProcessStruct {
    SilcPacketType *types;               /* Packets to process */
 -  SilcPacketCallbacks *callbacks;      /* Callbacks or NULL */
 +  const SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
    void *callback_context;
    SilcInt32 priority;                  /* Priority */
  } *SilcPacketProcess;
@@@ -81,7 -81,7 +81,7 @@@ struct SilcPacketStreamStruct 
    unsigned char *dst_id;               /* Destination ID */
    SilcUInt32 send_psn;                         /* Sending sequence */
    SilcUInt32 receive_psn;              /* Receiving sequence */
-   SilcAtomic8 refcnt;                  /* Reference counter */
+   SilcAtomic32 refcnt;                         /* Reference counter */
    SilcUInt8 sid;                       /* Security ID, set if IV included */
    unsigned int src_id_len  : 6;
    unsigned int src_id_type : 2;
@@@ -540,7 -540,7 +540,7 @@@ static void silc_packet_engine_context_
  
  SilcPacketEngine
  silc_packet_engine_start(SilcRng rng, SilcBool router,
 -                       SilcPacketCallbacks *callbacks,
 +                       const SilcPacketCallbacks *callbacks,
                         void *callback_context)
  {
    SilcPacketEngine engine;
@@@ -695,7 -695,7 +695,7 @@@ SilcPacketStream silc_packet_stream_cre
      return NULL;
  
    ps->stream = stream;
-   silc_atomic_init8(&ps->refcnt, 1);
+   silc_atomic_init32(&ps->refcnt, 1);
    silc_mutex_alloc(&ps->lock);
  
    /* Allocate out buffer */
@@@ -816,7 -816,7 +816,7 @@@ SilcPacketStream silc_packet_stream_add
      return NULL;
    ps->sc = stream->sc;
  
-   silc_atomic_init8(&ps->refcnt, 1);
+   silc_atomic_init32(&ps->refcnt, 1);
    silc_mutex_alloc(&ps->lock);
  
    /* Set the UDP packet stream as underlaying stream */
@@@ -884,7 -884,7 +884,7 @@@ void silc_packet_stream_destroy(SilcPac
    if (!stream)
      return;
  
-   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0) {
+   if (silc_atomic_sub_int32(&stream->refcnt, 1) > 0) {
      if (stream->destroyed)
        return;
      stream->destroyed = TRUE;
    silc_free(stream->src_id);
    silc_free(stream->dst_id);
  
-   silc_atomic_uninit8(&stream->refcnt);
+   silc_atomic_uninit32(&stream->refcnt);
    silc_mutex_free(stream->lock);
    silc_free(stream);
  }
@@@ -1001,7 -1001,7 +1001,7 @@@ void silc_packet_stream_set_iv_included
  /* Links `callbacks' to `stream' for specified packet types */
  
  static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
 -                                         SilcPacketCallbacks *callbacks,
 +                                         const SilcPacketCallbacks *callbacks,
                                           void *callback_context,
                                           int priority, va_list ap)
  {
      stream->process = silc_dlist_init();
      if (!stream->process) {
        silc_mutex_unlock(stream->lock);
+       silc_free(p);
        return FALSE;
      }
    }
  /* Links `callbacks' to `stream' for specified packet types */
  
  SilcBool silc_packet_stream_link(SilcPacketStream stream,
 -                               SilcPacketCallbacks *callbacks,
 +                               const SilcPacketCallbacks *callbacks,
                                 void *callback_context,
                                 int priority, ...)
  {
  /* Unlinks `callbacks' from `stream'. */
  
  void silc_packet_stream_unlink(SilcPacketStream stream,
 -                             SilcPacketCallbacks *callbacks,
 +                             const SilcPacketCallbacks *callbacks,
                               void *callback_context)
  {
    SilcPacketProcess p;
@@@ -1153,10 -1154,10 +1154,10 @@@ SilcBool silc_packet_get_sender(SilcPac
  
  void silc_packet_stream_ref(SilcPacketStream stream)
  {
-   silc_atomic_add_int8(&stream->refcnt, 1);
+   silc_atomic_add_int32(&stream->refcnt, 1);
    SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
-                 silc_atomic_get_int8(&stream->refcnt) - 1,
-                 silc_atomic_get_int8(&stream->refcnt)));
+                 silc_atomic_get_int32(&stream->refcnt) - 1,
+                 silc_atomic_get_int32(&stream->refcnt)));
  }
  
  /* Unreference packet stream */
  void silc_packet_stream_unref(SilcPacketStream stream)
  {
    SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
-                 silc_atomic_get_int8(&stream->refcnt),
-                 silc_atomic_get_int8(&stream->refcnt) - 1));
-   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0)
+                 silc_atomic_get_int32(&stream->refcnt),
+                 silc_atomic_get_int32(&stream->refcnt) - 1));
+   if (silc_atomic_sub_int32(&stream->refcnt, 1) > 0)
      return;
-   silc_atomic_add_int8(&stream->refcnt, 1);
+   silc_atomic_add_int32(&stream->refcnt, 1);
    silc_packet_stream_destroy(stream);
  }
  
@@@ -1323,6 -1324,6 +1324,7 @@@ SilcBool silc_packet_set_ids(SilcPacket
  {
    SilcUInt32 len;
    unsigned char tmp[32];
++  void *tmp_id;
  
    if (!src_id && !dst_id)
      return FALSE;
    if (src_id) {
      SILC_LOG_DEBUG(("Setting source ID to packet stream %p", stream));
  
--    silc_free(stream->src_id);
 -    stream->src_id = NULL;
      if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
--    stream->src_id = silc_memdup(tmp, len);
--    if (!stream->src_id) {
++    tmp_id = silc_memdup(tmp, len);
++    if (!tmp_id) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
++    silc_free(stream->src_id);
++    stream->src_id = tmp_id;
      stream->src_id_type = src_id_type;
      stream->src_id_len = len;
    }
    if (dst_id) {
      SILC_LOG_DEBUG(("Setting destination ID to packet stream %p", stream));
  
--    silc_free(stream->dst_id);
 -    stream->dst_id = NULL;
      if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
--    stream->dst_id = silc_memdup(tmp, len);
--    if (!stream->dst_id) {
++    tmp_id = silc_memdup(tmp, len);
++    if (!tmp_id) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
++    silc_free(stream->dst_id);
++    stream->dst_id = tmp_id;
      stream->dst_id_type = dst_id_type;
      stream->dst_id_len = len;
    }
@@@ -2340,7 -2343,7 +2344,7 @@@ silc_packet_wait_packet_receive(SilcPac
                                void *stream_context);
  
  /* Packet waiting callbacks */
 -static SilcPacketCallbacks silc_packet_wait_cbs =
 +static const SilcPacketCallbacks silc_packet_wait_cbs =
  {
    silc_packet_wait_packet_receive, NULL, NULL
  };
@@@ -2529,7 -2532,7 +2533,7 @@@ typedef struct 
  } *SilcPacketWrapperStream;
  
  /* Packet wrapper callbacks */
 -static SilcPacketCallbacks silc_packet_wrap_cbs =
 +static const SilcPacketCallbacks silc_packet_wrap_cbs =
  {
    silc_packet_wrap_packet_receive, NULL, NULL
  };