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

Simple merge
@@@ -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,13 -83,15 +84,16 @@@ 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 */
@@@ -1008,27 -1010,16 +1010,15 @@@ SilcBool silc_client_del_client(SilcCli
    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
@@@ -1084,11 -1075,31 +1074,32 @@@ SilcClientEntry silc_client_ref_client(
  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);
    }
  }
  
@@@ -1697,64 -1709,15 +1709,15 @@@ SilcBool silc_client_del_channel(SilcCl
    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
@@@ -1818,13 -1781,70 +1781,71 @@@ SilcChannelEntry silc_client_ref_channe
  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 */
@@@ -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;
    }