/*
- client_notify.c
+ client_notify.c
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 Pekka Riikonen
+ Copyright (C) 1997 - 2002 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
important packets sent by the server. They tell different things to the
client such as nick changes, mode changes etc. */
-#include "clientlibincludes.h"
+#include "silcincludes.h"
+#include "silcclient.h"
#include "client_internal.h"
typedef struct {
SilcClientCommandReplyContext reply =
(SilcClientCommandReplyContext)context2;
+ SILC_LOG_DEBUG(("Start"));
+
if (reply) {
SilcCommandStatus status;
unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL);
SILC_GET16_MSB(status, tmp);
- if (status != SILC_STATUS_OK) {
- silc_socket_free(res->sock);
- return;
- }
+ if (status != SILC_STATUS_OK)
+ goto out;
}
silc_client_notify_by_server(res->context, res->sock, res->packet);
- silc_socket_free(res->sock);
-}
-
-/* Destructor for the pending command callback */
-static void silc_client_notify_by_server_destructor(void *context)
-{
- SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
+ out:
+ silc_socket_free(res->sock);
silc_packet_context_free(res->packet);
silc_free(res);
}
silc_client_command_send(client, conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1, 3, idp->data, idp->len);
silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
- silc_client_notify_by_server_destructor,
silc_client_notify_by_server_pending, res);
silc_buffer_free(idp);
}
SilcChannelEntry channel;
SilcChannelUser chu;
SilcServerEntry server;
- SilcIDCacheEntry id_cache = NULL;
unsigned char *tmp;
- uint32 tmp_len, mode;
+ SilcUInt32 tmp_len, mode;
SILC_LOG_DEBUG(("Start"));
goto out;
/* Get the channel entry */
- channel = NULL;
- if (silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
- channel = (SilcChannelEntry)id_cache->context;
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
/* Get sender Client ID */
tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
goto out;
/* Get channel entry */
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel)
break;
- channel = (SilcChannelEntry)id_cache->context;
-
- /* Add client to channel */
- if (client_entry != conn->local_entry) {
+ /* Join the client to channel */
+ if (!silc_client_on_channel(channel, client_entry)) {
chu = silc_calloc(1, sizeof(*chu));
chu->client = client_entry;
- silc_list_add(channel->clients, chu);
+ chu->channel = channel;
+ silc_hash_table_add(channel->user_list, client_entry, chu);
+ silc_hash_table_add(client_entry->channels, channel, chu);
}
/* Notify application. The channel entry is sent last as this notify
SILC_ID_CHANNEL);
if (!channel_id)
goto out;
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel)
break;
- channel = (SilcChannelEntry)id_cache->context;
-
/* 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;
- }
+ chu = silc_client_on_channel(channel, client_entry);
+ if (chu) {
+ silc_hash_table_del(client_entry->channels, channel);
+ silc_hash_table_del(channel->user_list, client_entry);
+ silc_free(chu);
}
/* Notify application. The channel entry is sent last as this notify
SILC_ID_CHANNEL);
if (!channel_id)
goto out;
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel)
break;
- channel = (SilcChannelEntry)id_cache->context;
-
/* Notify application. The channel entry is sent last as this notify
is for channel but application don't know it from the arguments
sent by server. */
/* Find Client entry and if not found resolve it */
client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry2) {
+ /* Resolve the entry information */
silc_client_notify_by_server_resolve(client, conn, packet, client_id);
- goto out;
+
+ /* Add the new entry even though we resolved it. This is because we
+ want to replace the old entry with the new entry here right now. */
+ client_entry2 =
+ silc_client_add_client(client, conn, NULL, NULL, NULL,
+ silc_id_dup(client_id, SILC_ID_CLIENT),
+ client_entry->mode);
+
+ /* Replace old ID entry with new one on all channels. */
+ silc_client_replace_from_channels(client, conn, client_entry,
+ client_entry2);
} else {
if (client_entry2 != conn->local_entry)
silc_client_nickname_format(client, conn, client_entry2);
- }
- /* Remove the old from cache */
- silc_idcache_del_by_context(conn->client_cache, client_entry);
+ /* Remove the old from cache */
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
- /* Replace old ID entry with new one on all channels. */
- silc_client_replace_from_channels(client, conn, client_entry,
- client_entry2);
+ /* Replace old ID entry with new one on all channels. */
+ silc_client_replace_from_channels(client, conn, client_entry,
+ client_entry2);
- /* Notify application */
- client->internal->ops->notify(client, conn, type,
- client_entry, client_entry2);
+ /* Notify application */
+ client->internal->ops->notify(client, conn, type,
+ client_entry, client_entry2);
- /* Free data */
- silc_client_del_client_entry(client, conn, client_entry);
+ /* Free data */
+ silc_client_del_client_entry(client, conn, client_entry);
+ }
break;
case SILC_NOTIFY_TYPE_CMODE_CHANGE:
silc_id_payload_free(idp);
goto out;
}
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache)) {
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel) {
silc_id_payload_free(idp);
goto out;
}
- channel = (SilcChannelEntry)id_cache->context;
-
/* Save the new mode */
channel->mode = mode;
SILC_ID_CHANNEL);
if (!channel_id)
goto out;
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel)
break;
- channel = (SilcChannelEntry)id_cache->context;
-
/* Save the mode */
- silc_list_start(channel->clients);
- while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
- if (chu->client == client_entry) {
- chu->mode = mode;
- break;
- }
- }
+ chu = silc_client_on_channel(channel, client_entry2);
+ if (chu)
+ chu->mode = mode;
/* Notify application. The channel entry is sent last as this notify
is for channel but application don't know it from the arguments
channel_id = silc_id_payload_parse_id(tmp, tmp_len);
if (!channel_id)
goto out;
-
- /* Get the channel entry */
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
- break;
-
- channel = (SilcChannelEntry)id_cache->context;
-
- SILC_LOG_DEBUG(("Old Channel ID id(%s)",
- silc_id_render(channel->id, SILC_ID_CHANNEL)));
- /* Remove the old channel entry */
- silc_idcache_del_by_context(conn->channel_cache, channel);
+ /* Get the channel entry */
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel)
+ goto out;
- /* Free the old ID */
- silc_free(channel->id);
+ silc_free(channel_id);
/* Get the new ID */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!tmp)
goto out;
- channel->id = silc_id_payload_parse_id(tmp, tmp_len);
- if (!channel->id)
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id)
goto out;
- SILC_LOG_DEBUG(("New Channel ID id(%s)",
- silc_id_render(channel->id, SILC_ID_CHANNEL)));
-
- /* Add the channel entry again to ID cache */
- silc_idcache_add(conn->channel_cache, channel->channel_name,
- channel->id, channel, 0, NULL);
+ /* Replace the Channel ID */
+ silc_client_replace_channel_id(client, conn, channel, channel_id);
/* Notify application */
client->internal->ops->notify(client, conn, type, channel, channel);
SILC_ID_CHANNEL);
if (!channel_id)
goto out;
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel)
break;
- channel = (SilcChannelEntry)id_cache->context;
-
/* Get the kicker */
tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
if (!tmp)
/* Notify application. */
client->internal->ops->notify(client, conn, type, client_entry, tmp);
- if (client_entry != conn->local_entry) {
- /* Remove client from all channels */
- silc_client_remove_from_channels(client, conn, client_entry);
+ if (client_entry != conn->local_entry)
+ /* Remove the client from all channels and free it */
silc_client_del_client(client, conn, client_entry);
- }
break;
* from channels as they quit as well.
*/
SilcClientEntry *clients = NULL;
- uint32 clients_count = 0;
+ SilcUInt32 clients_count = 0;
int i;
SILC_LOG_DEBUG(("Notify: SIGNOFF"));
if (client_entry == conn->local_entry)
continue;
- silc_client_remove_from_channels(client, conn, client_entry);
+ /* Remove the client from all channels and free it */
silc_client_del_client(client, conn, client_entry);
}
silc_free(clients);