if (conn->server_cache)
silc_idcache_free(conn->server_cache);
- /* Free data (my ID is freed in above silc_client_del_client) */
- if (conn->nickname)
- silc_free(conn->nickname);
+ /* Free data (my ID is freed in above silc_client_del_client).
+ conn->nickname is freed when freeing the local_entry->nickname. */
if (conn->remote_host)
silc_free(conn->remote_host);
if (conn->local_id_data)
silc_free(msg);
}
+/* Auto-nicking callback to send NICK command to server. */
+
+SILC_TASK_CALLBACK(silc_client_send_auto_nick)
+{
+ SilcClientConnection conn = (SilcClientConnection)context;
+ SilcClient client = conn->client;
+
+ silc_client_command_send(client, conn, SILC_COMMAND_NICK,
+ ++conn->cmd_ident, 1, 1,
+ client->nickname, strlen(client->nickname));
+}
+
/* Processes the received new Client ID from server. Old Client ID is
deleted from cache and new one is added. */
if (!conn->local_entry)
conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
- conn->local_entry->nickname = strdup(conn->nickname);
+ conn->local_entry->nickname = conn->nickname;
if (!conn->local_entry->username)
conn->local_entry->username = strdup(client->username);
if (!conn->local_entry->hostname)
conn->local_entry->hostname = strdup(client->hostname);
- conn->local_entry->server = strdup(conn->remote_host);
+ if (!conn->local_entry->server)
+ conn->local_entry->server = strdup(conn->remote_host);
conn->local_entry->id = conn->local_id;
conn->local_entry->valid = TRUE;
-
+ if (!conn->local_entry->channels)
+ conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
+ NULL, NULL,
+ NULL, NULL, NULL,
+ TRUE);
+
/* Put it to the ID cache */
silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
(void *)conn->local_entry, 0, NULL);
if (connecting) {
/* Send NICK command if the nickname was set by the application (and is
- not same as the username). */
+ not same as the username). Send this with little timeout. */
if (client->nickname && strcmp(client->nickname, client->username))
- silc_client_command_send(client, conn, SILC_COMMAND_NICK,
- ++conn->cmd_ident, 1, 1,
- client->nickname, strlen(client->nickname));
+ silc_schedule_task_add(client->schedule, 0,
+ silc_client_send_auto_nick, conn,
+ 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
/* Issue INFO command to fetch the real server name and server information
and other stuff. */
}
}
-/* Processed received Channel ID for a channel. This is called when client
- joins to channel and server replies with channel ID. The ID is cached.
- Returns the created channel entry. This is also called when received
- channel ID in for example USERS command reply that we do not have. */
-
-SilcChannelEntry silc_client_new_channel_id(SilcClient client,
- SilcSocketConnection sock,
- char *channel_name,
- uint32 mode,
- SilcIDPayload idp)
-{
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcChannelEntry channel;
-
- SILC_LOG_DEBUG(("New channel ID"));
-
- channel = silc_calloc(1, sizeof(*channel));
- channel->channel_name = channel_name;
- channel->id = silc_id_payload_get_id(idp);
- channel->mode = mode;
- silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
-
- /* Put it to the ID cache */
- silc_idcache_add(conn->channel_cache, channel->channel_name,
- (void *)channel->id, (void *)channel, 0, NULL);
-
- return channel;
-}
-
-/* Removes a client entry from all channel it has joined. This really is
- a performance killer (client_entry should have pointers to channel
- entry list). */
+/* Removes a client entry from all channels it has joined. */
void silc_client_remove_from_channels(SilcClient client,
SilcClientConnection conn,
SilcClientEntry client_entry)
{
- SilcIDCacheEntry id_cache;
- SilcIDCacheList list;
- SilcChannelEntry channel;
+ SilcHashTableList htl;
SilcChannelUser chu;
- if (!silc_idcache_get_all(conn->channel_cache, &list))
- return;
-
- silc_idcache_list_first(list, &id_cache);
- channel = (SilcChannelEntry)id_cache->context;
-
- while (channel) {
-
- /* Remove client from channel */
- silc_list_start(channel->clients);
- while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
- if (chu->client == client_entry) {
- silc_list_del(channel->clients, chu);
- silc_free(chu);
- break;
- }
- }
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
-
- channel = (SilcChannelEntry)id_cache->context;
+ silc_hash_table_list(client_entry->channels, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+ silc_hash_table_del(chu->client->channels, chu->channel);
+ silc_hash_table_del(chu->channel->user_list, chu->client);
+ silc_free(chu);
}
- silc_idcache_list_free(list);
+ silc_hash_table_list_reset(&htl);
}
/* Replaces `old' client entries from all channels to `new' client entry.
SilcClientEntry old,
SilcClientEntry new)
{
- SilcIDCacheEntry id_cache;
- SilcIDCacheList list;
- SilcChannelEntry channel;
+ SilcHashTableList htl;
SilcChannelUser chu;
- if (!silc_idcache_get_all(conn->channel_cache, &list))
- return;
-
- silc_idcache_list_first(list, &id_cache);
- channel = (SilcChannelEntry)id_cache->context;
-
- while (channel) {
-
+ silc_hash_table_list(old->channels, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
/* Replace client entry */
- silc_list_start(channel->clients);
- while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
- if (chu->client == old) {
- chu->client = new;
- break;
- }
- }
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
+ silc_hash_table_del(chu->client->channels, chu->channel);
+ silc_hash_table_del(chu->channel->user_list, chu->client);
- channel = (SilcChannelEntry)id_cache->context;
+ chu->client = new;
+ silc_hash_table_add(chu->channel->user_list, chu->client, chu);
+ silc_hash_table_add(chu->client->channels, chu->channel, chu);
}
-
- silc_idcache_list_free(list);
+ silc_hash_table_list_reset(&htl);
}
/* Registers failure timeout to process the received failure packet