Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2007 Pekka Riikonen
+ Copyright (C) 2001 - 2008 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
NULL, NULL, NULL, TRUE);
if (!client_entry->channels) {
silc_free(client_entry->realname);
+ 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);
return NULL;
}
nick = silc_identifier_check(parsed, strlen(parsed),
SILC_STRING_UTF8, 128, NULL);
if (!nick) {
- silc_free(client_entry->realname);
silc_hash_table_free(client_entry->channels);
+ silc_free(client_entry->realname);
+ 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);
return NULL;
}
if (!silc_idcache_add(conn->internal->client_cache, nick,
&client_entry->id, client_entry)) {
silc_free(nick);
- silc_free(client_entry->realname);
silc_hash_table_free(client_entry->channels);
+ silc_free(client_entry->realname);
+ 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);
silc_mutex_unlock(conn->internal->lock);
return NULL;
if (!client_entry)
return FALSE;
- 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", client_entry));
+
+ if (silc_atomic_sub_int32(&client_entry->internal.deleted, 1) != 0) {
+ SILC_LOG_DEBUG(("Client entry %p already marked deleted", client_entry));
+ return FALSE;
}
silc_client_unref_client(client, conn, client_entry);
return TRUE;
-
}
/* Internal routine used to find client by ID and if not found this creates
void silc_client_unref_client(SilcClient client, SilcClientConnection conn,
SilcClientEntry client_entry)
{
- if (client_entry) {
- SilcBool ret;
+ SilcBool ret;
+
+ if (!client_entry)
+ return;
- 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_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 (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)));
+ if (silc_atomic_sub_int32(&client_entry->internal.refcnt, 1) > 0)
+ return;
- 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);
+ SILC_LOG_DEBUG(("Deleting client %p (%d)", client_entry,
+ silc_atomic_get_int32(&client_entry->internal.deleted)));
- if (ret) {
- /* Remove from channels */
- silc_client_remove_from_channels(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);
- /* Free the client entry data */
- silc_client_del_client_entry(client, conn, client_entry);
- }
+ 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);
}
}
if (!channel->channel_name) {
silc_rwlock_free(channel->internal.lock);
silc_atomic_uninit32(&channel->internal.refcnt);
+ silc_atomic_uninit32(&channel->internal.deleted);
silc_free(channel);
return NULL;
}
if (!channel->user_list) {
silc_rwlock_free(channel->internal.lock);
silc_atomic_uninit32(&channel->internal.refcnt);
+ silc_atomic_uninit32(&channel->internal.deleted);
silc_free(channel->channel_name);
silc_free(channel);
return NULL;
if (!channel_namec) {
silc_rwlock_free(channel->internal.lock);
silc_atomic_uninit32(&channel->internal.refcnt);
+ silc_atomic_uninit32(&channel->internal.deleted);
silc_free(channel->channel_name);
silc_hash_table_free(channel->user_list);
silc_free(channel);
&channel->id, channel)) {
silc_rwlock_free(channel->internal.lock);
silc_atomic_uninit32(&channel->internal.refcnt);
+ silc_atomic_uninit32(&channel->internal.deleted);
silc_free(channel_namec);
silc_free(channel->channel_name);
silc_hash_table_free(channel->user_list);
if (!channel)
return FALSE;
- 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", channel));
+
+ if (silc_atomic_sub_int32(&channel->internal.deleted, 1) != 0) {
+ SILC_LOG_DEBUG(("Channel entry %p already marked deleted", channel));
return FALSE;
}
void silc_client_unref_channel(SilcClient client, SilcClientConnection conn,
SilcChannelEntry channel_entry)
{
- if (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));
+
+ if (silc_atomic_sub_int32(&channel_entry->internal.refcnt, 1) > 0)
+ return;
- SILC_LOG_DEBUG(("Deleting channel %p", 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,
+ 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 */
silc_rwlock_alloc(&server_entry->internal.lock);
silc_atomic_init32(&server_entry->internal.refcnt, 0);
+ silc_atomic_init32(&server_entry->internal.deleted, 1);
server_entry->id = *server_id;
if (server_name)
server_entry->server_name = strdup(server_name);
if (!server_namec) {
silc_free(server_entry->server_name);
silc_free(server_entry->server_info);
+ silc_atomic_uninit32(&server_entry->internal.deleted);
+ silc_atomic_uninit32(&server_entry->internal.refcnt);
+ silc_rwlock_free(server_entry->internal.lock);
silc_free(server_entry);
return NULL;
}
silc_free(server_namec);
silc_free(server_entry->server_name);
silc_free(server_entry->server_info);
+ silc_atomic_uninit32(&server_entry->internal.deleted);
+ silc_atomic_uninit32(&server_entry->internal.refcnt);
+ silc_rwlock_free(server_entry->internal.lock);
silc_free(server_entry);
silc_mutex_unlock(conn->internal->lock);
return NULL;
SilcBool silc_client_del_server(SilcClient client, SilcClientConnection conn,
SilcServerEntry server)
{
- SilcIDCacheEntry id_cache;
- SilcBool ret = TRUE;
- char *namec;
-
if (!server)
return FALSE;
- if (silc_atomic_sub_int32(&server->internal.refcnt, 1) > 0)
+ if (silc_atomic_sub_int32(&server->internal.deleted, 1) != 0)
return FALSE;
- SILC_LOG_DEBUG(("Deleting server %p", server));
-
- silc_mutex_lock(conn->internal->lock);
- if (silc_idcache_find_by_context(conn->internal->server_cache, server,
- &id_cache)) {
- namec = id_cache->name;
- ret = silc_idcache_del_by_context(conn->internal->server_cache,
- server, NULL);
- silc_free(namec);
- }
- silc_mutex_unlock(conn->internal->lock);
-
- silc_free(server->server_name);
- silc_free(server->server_info);
- if (server->public_key)
- silc_pkcs_public_key_free(server->public_key);
- silc_atomic_uninit32(&server->internal.refcnt);
- silc_rwlock_free(server->internal.lock);
- silc_free(server);
-
- return ret;
+ silc_client_unref_server(client, conn, server);
+ return TRUE;
}
/* Updates the `server_entry' with the new information sent as argument. */
void silc_client_unref_server(SilcClient client, SilcClientConnection conn,
SilcServerEntry server_entry)
{
- if (server_entry) {
- SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry,
- 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);
+ SilcBool ret;
+ SilcIDCacheEntry id_cache;
+ char *namec;
+
+ if (!server_entry)
+ return;
+
+ if (silc_atomic_sub_int32(&server_entry->internal.refcnt, 1) > 0)
+ return;
+
+ SILC_LOG_DEBUG(("Deleting server %p", server_entry));
+
+ silc_mutex_lock(conn->internal->lock);
+ if (silc_idcache_find_by_context(conn->internal->server_cache, server_entry,
+ &id_cache)) {
+ namec = id_cache->name;
+ ret = silc_idcache_del_by_context(conn->internal->server_cache,
+ server_entry, NULL);
+ silc_free(namec);
}
+ silc_mutex_unlock(conn->internal->lock);
+
+ silc_free(server_entry->server_name);
+ silc_free(server_entry->server_info);
+ if (server_entry->public_key)
+ silc_pkcs_public_key_free(server_entry->public_key);
+ silc_atomic_uninit32(&server_entry->internal.deleted);
+ silc_atomic_uninit32(&server_entry->internal.refcnt);
+ silc_rwlock_free(server_entry->internal.lock);
+ silc_free(server_entry);
}
/* Free server entry list */