X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fcommand_reply.c;h=fba3147b535dcdaef6c34867a48a76327b90f49f;hp=9a8b9fe6b1b82837e610accd5193b05a7737af4c;hb=a818c5b5411bbc4436d1c5f011236985c96bb787;hpb=e5d8d3db6caa344b3d419b884556c21b15e7d123 diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 9a8b9fe6..fba3147b 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -1,22 +1,22 @@ /* - command_reply.c + command_reply.c - Author: Pekka Riikonen + Author: Pekka Riikonen - 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 GNU General Public License for more details. */ +/* $Id$ */ /* * Command reply functions are "the otherside" of the command functions. * Reply to a command sent by server is handled by these functions. @@ -31,48 +31,16 @@ * necessary data already in hand without redundant searching. If ID is * received but ID entry does not exist, NULL is sent. */ -/* $Id$ */ -#include "clientlibincludes.h" +#include "silcincludes.h" +#include "silcclient.h" #include "client_internal.h" -/* Client command reply list. */ -SilcClientCommandReply silc_command_reply_list[] = -{ - SILC_CLIENT_CMD_REPLY(whois, WHOIS), - SILC_CLIENT_CMD_REPLY(whowas, WHOWAS), - SILC_CLIENT_CMD_REPLY(identify, IDENTIFY), - SILC_CLIENT_CMD_REPLY(nick, NICK), - SILC_CLIENT_CMD_REPLY(list, LIST), - SILC_CLIENT_CMD_REPLY(topic, TOPIC), - SILC_CLIENT_CMD_REPLY(invite, INVITE), - SILC_CLIENT_CMD_REPLY(kill, KILL), - SILC_CLIENT_CMD_REPLY(info, INFO), - SILC_CLIENT_CMD_REPLY(connect, CONNECT), - SILC_CLIENT_CMD_REPLY(ping, PING), - SILC_CLIENT_CMD_REPLY(oper, OPER), - SILC_CLIENT_CMD_REPLY(join, JOIN), - SILC_CLIENT_CMD_REPLY(motd, MOTD), - SILC_CLIENT_CMD_REPLY(umode, UMODE), - SILC_CLIENT_CMD_REPLY(cmode, CMODE), - SILC_CLIENT_CMD_REPLY(cumode, CUMODE), - SILC_CLIENT_CMD_REPLY(kick, KICK), - SILC_CLIENT_CMD_REPLY(ban, BAN), - SILC_CLIENT_CMD_REPLY(close, CLOSE), - SILC_CLIENT_CMD_REPLY(shutdown, SHUTDOWN), - SILC_CLIENT_CMD_REPLY(silcoper, SILCOPER), - SILC_CLIENT_CMD_REPLY(leave, LEAVE), - SILC_CLIENT_CMD_REPLY(users, USERS), - SILC_CLIENT_CMD_REPLY(getkey, GETKEY), - - { NULL, 0 }, -}; - const SilcCommandStatusMessage silc_command_status_messages[] = { { STAT(NO_SUCH_NICK), "There was no such nickname" }, { STAT(NO_SUCH_CHANNEL), "There was no such channel" }, - { STAT(NO_SUCH_SERVER), "No such server" }, + { STAT(NO_SUCH_SERVER), "There was no such server" }, { STAT(TOO_MANY_TARGETS), "Duplicate recipients. No message delivered" }, { STAT(NO_RECIPIENT), "No recipient given" }, { STAT(UNKNOWN_COMMAND), "Unknown command" }, @@ -113,14 +81,16 @@ const SilcCommandStatusMessage silc_command_status_messages[] = { }; /* Command reply operation that is called at the end of all command replys. Usage: COMMAND_REPLY((ARGS, argument1, argument2, etc...)), */ -#define COMMAND_REPLY(args) cmd->client->ops->command_reply args -#define ARGS cmd->client, cmd->sock->user_data, \ +#define COMMAND_REPLY(args) cmd->client->internal->ops->command_reply args +#define ARGS cmd->client, cmd->sock->user_data, \ cmd->payload, TRUE, silc_command_get(cmd->payload), status /* Error reply to application. Usage: COMMAND_REPLY_ERROR; */ -#define COMMAND_REPLY_ERROR cmd->client->ops->command_reply(cmd->client, \ - cmd->sock->user_data, cmd->payload, FALSE, \ - silc_command_get(cmd->payload), status) +#define COMMAND_REPLY_ERROR cmd->client->internal->ops-> \ + command_reply(cmd->client, cmd->sock->user_data, cmd->payload, \ + FALSE, silc_command_get(cmd->payload), status) + +#define SAY cmd->client->internal->ops->say /* All functions that call the COMMAND_CHECK_STATUS or the COMMAND_CHECK_STATUS_LIST macros must have out: goto label. */ @@ -155,14 +125,14 @@ void silc_client_command_reply_process(SilcClient client, SilcPacketContext *packet) { SilcBuffer buffer = packet->buffer; - SilcClientCommandReply *cmd; + SilcClientCommand cmd; SilcClientCommandReplyContext ctx; SilcCommandPayload payload; SilcCommand command; - uint16 ident; - + SilcCommandCb reply = NULL; + /* Get command reply payload from packet */ - payload = silc_command_payload_parse(buffer); + payload = silc_command_payload_parse(buffer->data, buffer->len); if (!payload) { /* Silently ignore bad reply packet */ SILC_LOG_DEBUG(("Bad command reply packet")); @@ -177,24 +147,35 @@ void silc_client_command_reply_process(SilcClient client, ctx->payload = payload; ctx->args = silc_command_get_args(ctx->payload); ctx->packet = packet; - ident = silc_command_get_ident(ctx->payload); - + ctx->ident = silc_command_get_ident(ctx->payload); + /* Check for pending commands and mark to be exeucted */ silc_client_command_pending_check(sock->user_data, ctx, - silc_command_get(ctx->payload), ident); + silc_command_get(ctx->payload), + ctx->ident); /* Execute command reply */ + command = silc_command_get(ctx->payload); - for (cmd = silc_command_reply_list; cmd->cb; cmd++) - if (cmd->cmd == command) - break; - if (cmd == NULL || !cmd->cb) { - silc_free(ctx); - return; + /* Try to find matching the command identifier */ + silc_list_start(client->internal->commands); + while ((cmd = silc_list_get(client->internal->commands)) != SILC_LIST_END) { + if (cmd->cmd == command && !cmd->ident) + reply = cmd->reply; + if (cmd->cmd == command && cmd->ident == ctx->ident) { + (*cmd->reply)((void *)ctx, NULL); + break; + } } - cmd->cb(ctx, NULL); + if (cmd == SILC_LIST_END) { + if (reply) + /* No specific identifier for command reply, call first one found */ + (*reply)(ctx, NULL); + else + silc_free(ctx); + } } /* Returns status message string */ @@ -226,31 +207,35 @@ void silc_client_command_reply_free(SilcClientCommandReplyContext cmd) static void silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, - SilcCommandStatus status) + SilcCommandStatus status, + bool notify) { SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcClientID *client_id; - SilcIDCacheEntry id_cache = NULL; SilcClientEntry client_entry = NULL; int argc; - uint32 len; + SilcUInt32 len; unsigned char *id_data, *tmp; char *nickname = NULL, *username = NULL; char *realname = NULL; - uint32 idle = 0, mode = 0; + SilcUInt32 idle = 0, mode = 0; SilcBuffer channels = NULL; + unsigned char *fingerprint; + SilcUInt32 fingerprint_len; argc = silc_argument_get_arg_num(cmd->args); id_data = silc_argument_get_arg_type(cmd->args, 2, &len); if (!id_data) { - COMMAND_REPLY_ERROR; + if (notify) + COMMAND_REPLY_ERROR; return; } client_id = silc_id_payload_parse_id(id_data, len); if (!client_id) { - COMMAND_REPLY_ERROR; + if (notify) + COMMAND_REPLY_ERROR; return; } @@ -258,7 +243,8 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, username = silc_argument_get_arg_type(cmd->args, 4, &len); realname = silc_argument_get_arg_type(cmd->args, 5, &len); if (!nickname || !username || !realname) { - COMMAND_REPLY_ERROR; + if (notify) + COMMAND_REPLY_ERROR; return; } @@ -277,26 +263,33 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, if (tmp) SILC_GET32_MSB(idle, tmp); + fingerprint = silc_argument_get_arg_type(cmd->args, 9, &fingerprint_len); + /* Check if we have this client cached already. */ - if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); + if (!client_entry) { SILC_LOG_DEBUG(("Adding new client entry")); client_entry = silc_client_add_client(cmd->client, conn, nickname, username, realname, client_id, mode); } else { - client_entry = (SilcClientEntry)id_cache->context; silc_client_update_client(cmd->client, conn, client_entry, nickname, username, realname, mode); silc_free(client_id); } + if (fingerprint && !client_entry->fingerprint) { + client_entry->fingerprint = silc_memdup(fingerprint, fingerprint_len); + client_entry->fingerprint_len = fingerprint_len; + } + + if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) + client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; + /* Notify application */ - if (!cmd->callback) + if (!cmd->callback && notify) COMMAND_REPLY((ARGS, client_entry, nickname, username, realname, - channels, mode, idle)); + channels, mode, idle, fingerprint)); if (channels) silc_buffer_free(channels); @@ -308,12 +301,13 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, SILC_CLIENT_CMD_REPLY_FUNC(whois) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; COMMAND_CHECK_STATUS_LIST; /* Save WHOIS info */ - silc_client_command_reply_whois_save(cmd, status); + silc_client_command_reply_whois_save(cmd, status, TRUE); /* Pending callbacks are not executed if this was an list entry */ if (status != SILC_STATUS_OK && @@ -324,7 +318,27 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS); + + /* If we received notify for invalid ID we'll remove the ID if we + have it cached. */ + if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { + SilcClientEntry client_entry; + SilcUInt32 tmp_len; + unsigned char *tmp = + silc_argument_get_arg_type(silc_command_get_args(cmd->payload), + 2, &tmp_len); + if (tmp) { + SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len); + if (client_id) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, + client_id); + if (client_entry) + silc_client_del_client(cmd->client, conn, client_entry); + silc_free(client_id); + } + } + } + silc_client_command_reply_free(cmd); } @@ -336,9 +350,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas) SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; SilcClientID *client_id; - SilcIDCacheEntry id_cache = NULL; SilcClientEntry client_entry = NULL; - uint32 len; + SilcUInt32 len; unsigned char *id_data; char *nickname, *username; char *realname = NULL; @@ -358,11 +371,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas) } /* Get the client entry, if exists */ - if (silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) - client_entry = (SilcClientEntry)id_cache->context; + client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); silc_free(client_id); nickname = silc_argument_get_arg_type(cmd->args, 3, &len); @@ -386,14 +395,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas) } out: - SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS); + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS); silc_client_command_reply_free(cmd); } static void silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, - SilcCommandStatus status) + SilcCommandStatus status, + bool notify) { SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcClient client = cmd->client; @@ -405,7 +414,7 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, SilcServerEntry server_entry; SilcChannelEntry channel_entry; int argc; - uint32 len; + SilcUInt32 len; unsigned char *id_data; char *name = NULL, *info = NULL; SilcIDPayload idp = NULL; @@ -415,12 +424,14 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, id_data = silc_argument_get_arg_type(cmd->args, 2, &len); if (!id_data) { - COMMAND_REPLY_ERROR; + if (notify) + COMMAND_REPLY_ERROR; return; } - idp = silc_id_payload_parse_data(id_data, len); + idp = silc_id_payload_parse(id_data, len); if (!idp) { - COMMAND_REPLY_ERROR; + if (notify) + COMMAND_REPLY_ERROR; return; } @@ -436,23 +447,23 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, SILC_LOG_DEBUG(("Received client information")); /* Check if we have this client cached already. */ - if (!silc_idcache_find_by_id_one_ext(conn->client_cache, - (void *)client_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); + if (!client_entry) { SILC_LOG_DEBUG(("Adding new client entry")); client_entry = silc_client_add_client(cmd->client, conn, name, info, NULL, silc_id_dup(client_id, id_type), 0); } else { - client_entry = (SilcClientEntry)id_cache->context; silc_client_update_client(cmd->client, conn, client_entry, name, info, NULL, 0); } + if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) + client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; + /* Notify application */ - COMMAND_REPLY((ARGS, client_entry, name, info)); + if (notify) + COMMAND_REPLY((ARGS, client_entry, name, info)); break; case SILC_ID_SERVER: @@ -474,13 +485,15 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, /* Add server to cache */ silc_idcache_add(conn->server_cache, server_entry->server_name, - server_entry->server_id, (void *)server_entry, FALSE); + server_entry->server_id, (void *)server_entry, + 0, NULL); } else { server_entry = (SilcServerEntry)id_cache->context; } /* Notify application */ - COMMAND_REPLY((ARGS, server_entry, name, info)); + if (notify) + COMMAND_REPLY((ARGS, server_entry, name, info)); break; case SILC_ID_CHANNEL: @@ -489,20 +502,20 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, SILC_LOG_DEBUG(("Received channel information")); /* Check if we have this channel cached already. */ - if (!silc_idcache_find_by_id_one(conn->channel_cache, - (void *)channel_id, &id_cache)) { + channel_entry = silc_client_get_channel_by_id(client, conn, channel_id); + if (!channel_entry) { if (!name) break; - SILC_LOG_DEBUG(("Adding new channel entry")); - channel_entry = silc_client_new_channel_id(client, conn->sock, - strdup(name), 0, idp); - } else { - channel_entry = (SilcChannelEntry)id_cache->context; + /* Add new channel entry */ + channel_entry = silc_client_add_channel(client, conn, name, 0, + channel_id); + channel_id = NULL; } /* Notify application */ - COMMAND_REPLY((ARGS, channel_entry, name, info)); + if (notify) + COMMAND_REPLY((ARGS, channel_entry, name, info)); break; } @@ -519,12 +532,13 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, SILC_CLIENT_CMD_REPLY_FUNC(identify) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; COMMAND_CHECK_STATUS_LIST; /* Save IDENTIFY info */ - silc_client_command_reply_identify_save(cmd, status); + silc_client_command_reply_identify_save(cmd, status, TRUE); /* Pending callbacks are not executed if this was an list entry */ if (status != SILC_STATUS_OK && @@ -535,7 +549,27 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY); + + /* If we received notify for invalid ID we'll remove the ID if we + have it cached. */ + if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { + SilcClientEntry client_entry; + SilcUInt32 tmp_len; + unsigned char *tmp = + silc_argument_get_arg_type(silc_command_get_args(cmd->payload), + 2, &tmp_len); + if (tmp) { + SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len); + if (client_id) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, + client_id); + if (client_entry) + silc_client_del_client(cmd->client, conn, client_entry); + silc_free(client_id); + } + } + } + silc_client_command_reply_free(cmd); } @@ -549,30 +583,29 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick) SilcCommandStatus status; SilcIDPayload idp; unsigned char *tmp; - uint32 argc, len; + SilcUInt32 argc, len; SILC_LOG_DEBUG(("Start")); SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Cannot set nickname: %s", - silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "Cannot set nickname: %s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } argc = silc_argument_get_arg_num(cmd->args); if (argc < 2 || argc > 2) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Cannot set nickname: bad reply to command"); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "Cannot set nickname: bad reply to command"); COMMAND_REPLY_ERROR; goto out; } /* Take received Client ID */ tmp = silc_argument_get_arg_type(cmd->args, 2, &len); - idp = silc_id_payload_parse_data(tmp, len); + idp = silc_id_payload_parse(tmp, len); if (!idp) { COMMAND_REPLY_ERROR; goto out; @@ -580,11 +613,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick) silc_client_receive_new_id(cmd->client, cmd->sock, idp); /* Notify application */ + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK); COMMAND_REPLY((ARGS, conn->local_entry)); + silc_client_command_reply_free(cmd); + return; out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_NICK); silc_client_command_reply_free(cmd); } @@ -595,7 +630,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(list) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcCommandStatus status; unsigned char *tmp, *name, *topic; - uint32 usercount = 0; + SilcUInt32 usercount = 0; COMMAND_CHECK_STATUS_LIST; @@ -617,7 +652,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(list) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LIST); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_LIST); silc_client_command_reply_free(cmd); } @@ -630,15 +664,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic) SilcCommandStatus status; SilcChannelEntry channel; SilcChannelID *channel_id = NULL; - SilcIDCacheEntry id_cache = NULL; unsigned char *tmp; char *topic; - uint32 argc, len; + SilcUInt32 argc, len; SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -664,21 +697,18 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic) goto out; /* Get the channel entry */ - if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - &id_cache)) { + channel = silc_client_get_channel_by_id(cmd->client, conn, channel_id); + if (!channel) { silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } - channel = (SilcChannelEntry)id_cache->context; - /* Notify application */ COMMAND_REPLY((ARGS, channel, topic)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_TOPIC); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_TOPIC); silc_client_command_reply_free(cmd); } @@ -691,15 +721,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) SilcCommandStatus status; SilcChannelEntry channel; SilcChannelID *channel_id; - SilcIDCacheEntry id_cache; unsigned char *tmp; - uint32 len; + SilcUInt32 len; tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -714,14 +743,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) goto out; /* Get the channel entry */ - if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - &id_cache)) { + channel = silc_client_get_channel_by_id(cmd->client, conn, channel_id); + if (!channel) { silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } - - channel = (SilcChannelEntry)id_cache->context; /* Get the invite list */ tmp = silc_argument_get_arg_type(cmd->args, 3, &len); @@ -731,7 +758,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INVITE); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE); silc_client_command_reply_free(cmd); } @@ -745,8 +771,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill) SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -756,7 +782,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KILL); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_KILL); silc_client_command_reply_free(cmd); } @@ -773,13 +798,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) SilcServerEntry server; SilcServerID *server_id = NULL; char *server_name, *server_info; - uint32 len; + SilcUInt32 len; + + SILC_LOG_DEBUG(("Start")); tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s", + silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -815,7 +842,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) /* Add it to the cache */ silc_idcache_add(conn->server_cache, server->server_name, - server->server_id, (void *)server, FALSE); + server->server_id, (void *)server, 0, NULL); } else { server = (SilcServerEntry)id_cache->context; } @@ -825,7 +852,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO); silc_free(server_id); silc_client_command_reply_free(cmd); } @@ -843,8 +869,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping) SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -852,18 +878,20 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping) curtime = time(NULL); id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_len, cmd->packet->src_id_type); - if (!id) { + if (!id || !conn->ping) { COMMAND_REPLY_ERROR; goto out; } for (i = 0; i < conn->ping_count; i++) { + if (!conn->ping[i].dest_id) + continue; if (SILC_ID_SERVER_COMPARE(conn->ping[i].dest_id, id)) { diff = curtime - conn->ping[i].start_time; - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "Ping reply from %s: %d second%s", - conn->ping[i].dest_name, diff, - diff == 1 ? "" : "s"); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Ping reply from %s: %d second%s", + conn->ping[i].dest_name, diff, + diff == 1 ? "" : "s"); conn->ping[i].start_time = 0; silc_free(conn->ping[i].dest_id); @@ -881,7 +909,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PING); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_PING); silc_client_command_reply_free(cmd); } @@ -892,11 +919,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; - SilcIDPayload idp = NULL; SilcChannelEntry channel; - SilcIDCacheEntry id_cache = NULL; SilcChannelUser chu; - uint32 argc, mode, len, list_count; + SilcChannelID *channel_id; + SilcUInt32 argc, mode = 0, len, list_count; char *topic, *tmp, *channel_name = NULL, *hmac; SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL; int i; @@ -905,16 +931,17 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + if (status != SILC_STATUS_ERR_USER_ON_CHANNEL) + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } argc = silc_argument_get_arg_num(cmd->args); if (argc < 7 || argc > 14) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Cannot join channel: Bad reply packet"); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "Cannot join channel: Bad reply packet"); COMMAND_REPLY_ERROR; goto out; } @@ -922,26 +949,24 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) /* Get channel name */ tmp = silc_argument_get_arg_type(cmd->args, 2, NULL); if (!tmp) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Cannot join channel: Bad reply packet"); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "Cannot join channel: Bad reply packet"); COMMAND_REPLY_ERROR; goto out; } - channel_name = strdup(tmp); + channel_name = tmp; /* Get Channel ID */ tmp = silc_argument_get_arg_type(cmd->args, 3, &len); if (!tmp) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Cannot join channel: Bad reply packet"); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "Cannot join channel: Bad reply packet"); COMMAND_REPLY_ERROR; - silc_free(channel_name); goto out; } - idp = silc_id_payload_parse_data(tmp, len); - if (!idp) { + channel_id = silc_id_payload_parse_id(tmp, len); + if (!channel_id) { COMMAND_REPLY_ERROR; - silc_free(channel_name); goto out; } @@ -949,8 +974,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) tmp = silc_argument_get_arg_type(cmd->args, 5, NULL); if (tmp) SILC_GET32_MSB(mode, tmp); - else - mode = 0; /* Get channel key */ tmp = silc_argument_get_arg_type(cmd->args, 7, &len); @@ -963,15 +986,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) /* Get topic */ topic = silc_argument_get_arg_type(cmd->args, 10, NULL); - /* If we have the channel entry, remove it and create a new one */ + /* Check whether we have this channel entry already. */ channel = silc_client_get_channel(cmd->client, conn, channel_name); - if (channel) - silc_client_del_channel(cmd->client, conn, channel); - - /* Save received Channel ID. This actually creates the channel */ - channel = silc_client_new_channel_id(cmd->client, cmd->sock, channel_name, - mode, idp); - silc_id_payload_free(idp); + if (channel) { + if (!SILC_ID_CHANNEL_COMPARE(channel->id, channel_id)) + silc_client_replace_channel_id(cmd->client, conn, channel, channel_id); + } else { + /* Create new channel entry */ + channel = silc_client_add_channel(cmd->client, conn, channel_name, + mode, channel_id); + } conn->current_channel = channel; @@ -979,11 +1003,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) hmac = silc_argument_get_arg_type(cmd->args, 11, NULL); if (hmac) { if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Cannot join channel: Unsupported HMAC `%s'", - hmac); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "Cannot join channel: Unsupported HMAC `%s'", hmac); COMMAND_REPLY_ERROR; - silc_free(channel_name); goto out; } } @@ -1014,8 +1036,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) /* Add clients we received in the reply to the channel */ for (i = 0; i < list_count; i++) { - uint16 idp_len; - uint32 mode; + SilcUInt16 idp_len; + SilcUInt32 mode; SilcClientID *client_id; SilcClientEntry client_entry; @@ -1030,27 +1052,23 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) SILC_GET32_MSB(mode, client_mode_list->data); /* Check if we have this client cached already. */ - if (!silc_idcache_find_by_id_one_ext(conn->client_cache, - (void *)client_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); + if (!client_entry) { /* No, we don't have it, add entry for it. */ client_entry = silc_client_add_client(cmd->client, conn, NULL, NULL, NULL, silc_id_dup(client_id, SILC_ID_CLIENT), 0); - } else { - /* Yes, we have it already */ - client_entry = (SilcClientEntry)id_cache->context; } - /* Join the client to the channel */ + /* Join client to the channel */ chu = silc_calloc(1, sizeof(*chu)); chu->client = client_entry; + chu->channel = channel; chu->mode = mode; - silc_list_add(channel->clients, chu); - silc_free(client_id); + silc_hash_table_add(channel->user_list, client_entry, chu); + silc_hash_table_add(client_entry->channels, channel, chu); + silc_free(client_id); silc_buffer_pull(client_id_list, idp_len); silc_buffer_pull(client_mode_list, 4); } @@ -1060,11 +1078,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) client_mode_list->head); /* Save channel key */ - if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) - silc_client_save_channel_key(conn, keyp, channel); - - /* Client is now joined to the channel */ - channel->on_channel = TRUE; + if (keyp && !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) + silc_client_save_channel_key(cmd->client, conn, keyp, channel); /* Notify application */ COMMAND_REPLY((ARGS, channel_name, channel, mode, 0, @@ -1074,7 +1089,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_JOIN); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN); silc_client_command_reply_free(cmd); if (keyp) @@ -1092,15 +1106,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; - uint32 argc, i; + SilcUInt32 argc, i; unsigned char *tmp; char *motd = NULL, *cp, line[256]; tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; return; } @@ -1129,8 +1143,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) if (i == 2) line[0] = ' '; - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "%s", line); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", line); if (!strlen(cp)) break; @@ -1144,7 +1157,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_MOTD); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD); silc_client_command_reply_free(cmd); } @@ -1156,13 +1168,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode) SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; unsigned char *tmp; - uint32 mode; + SilcUInt32 mode; tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1181,7 +1193,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_UMODE); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_UMODE); silc_client_command_reply_free(cmd); } @@ -1193,16 +1204,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; unsigned char *tmp; - uint32 mode; - SilcIDCacheEntry id_cache; + SilcUInt32 mode; SilcChannelID *channel_id; SilcChannelEntry channel; - uint32 len; + SilcUInt32 len; SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1216,15 +1226,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) goto out; /* Get the channel entry */ - if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - &id_cache)) { + channel = silc_client_get_channel_by_id(cmd->client, conn, channel_id); + if (!channel) { silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } - channel = (SilcChannelEntry)id_cache->context; - /* Get channel mode */ tmp = silc_argument_get_arg_type(cmd->args, 3, NULL); if (!tmp) { @@ -1244,7 +1252,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CMODE); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CMODE); silc_client_command_reply_free(cmd); } @@ -1255,19 +1262,18 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; - SilcIDCacheEntry id_cache = NULL; SilcClientID *client_id; SilcChannelID *channel_id; SilcClientEntry client_entry; SilcChannelEntry channel; SilcChannelUser chu; unsigned char *modev, *tmp, *id; - uint32 len, mode; + SilcUInt32 len, mode; SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1288,15 +1294,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) goto out; /* Get the channel entry */ - if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - &id_cache)) { + channel = silc_client_get_channel_by_id(cmd->client, conn, channel_id); + if (!channel) { silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } - channel = (SilcChannelEntry)id_cache->context; - /* Get Client ID */ id = silc_argument_get_arg_type(cmd->args, 4, &len); if (!id) { @@ -1312,27 +1316,19 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) } /* Get client entry */ - if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); + if (!client_entry) { silc_free(channel_id); silc_free(client_id); COMMAND_REPLY_ERROR; goto out; } - client_entry = (SilcClientEntry)id_cache->context; - /* Save the mode */ SILC_GET32_MSB(mode, modev); - 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_entry); + if (chu) + chu->mode = mode; /* Notify application */ COMMAND_REPLY((ARGS, mode, channel, client_entry)); @@ -1341,7 +1337,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CUMODE); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CUMODE); silc_client_command_reply_free(cmd); } @@ -1355,8 +1350,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(kick) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1366,7 +1361,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(kick) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KICK); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_KICK); silc_client_command_reply_free(cmd); } @@ -1380,8 +1374,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(silcoper) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1391,7 +1385,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(silcoper) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SILCOPER); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_SILCOPER); silc_client_command_reply_free(cmd); } @@ -1405,8 +1398,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(oper) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1416,7 +1409,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(oper) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_OPER); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_OPER); silc_client_command_reply_free(cmd); } @@ -1430,8 +1422,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(connect) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1441,7 +1433,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(connect) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CONNECT); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CONNECT); silc_client_command_reply_free(cmd); } @@ -1450,17 +1441,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; - SilcIDCacheEntry id_cache = NULL; SilcChannelEntry channel; SilcChannelID *channel_id; unsigned char *tmp; - uint32 len; + SilcUInt32 len; tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1475,15 +1465,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban) goto out; /* Get the channel entry */ - if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - &id_cache)) { + channel = silc_client_get_channel_by_id(cmd->client, conn, channel_id); + if (!channel) { silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } - channel = (SilcChannelEntry)id_cache->context; - /* Get the ban list */ tmp = silc_argument_get_arg_type(cmd->args, 3, &len); @@ -1492,7 +1480,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_BAN); silc_client_command_reply_free(cmd); } @@ -1506,8 +1493,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(close) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1517,7 +1504,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(close) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CLOSE); silc_client_command_reply_free(cmd); } @@ -1531,8 +1517,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1542,7 +1528,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SHUTDOWN); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_SHUTDOWN); silc_client_command_reply_free(cmd); } @@ -1558,8 +1543,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1569,10 +1554,33 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LEAVE); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_LEAVE); silc_client_command_reply_free(cmd); } +/* Channel resolving callback for USERS command reply. */ + +static void silc_client_command_reply_users_cb(SilcClient client, + SilcClientConnection conn, + SilcChannelEntry *channels, + SilcUInt32 channels_count, + void *context) +{ + if (!channels_count) { + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcCommandStatus status = SILC_STATUS_ERR_NO_SUCH_CHANNEL; + + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); + COMMAND_REPLY_ERROR; + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS); + silc_client_command_reply_free(cmd); + return; + } + + silc_client_command_reply_users(context, NULL); +} + /* Reply to USERS command. Received list of client ID's and theirs modes on the channel we requested. */ @@ -1581,25 +1589,25 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; - SilcIDCacheEntry id_cache = NULL; SilcChannelEntry channel; + SilcClientEntry client_entry; SilcChannelUser chu; SilcChannelID *channel_id = NULL; SilcBuffer client_id_list = NULL; SilcBuffer client_mode_list = NULL; unsigned char *tmp; - uint32 tmp_len, list_count; + SilcUInt32 tmp_len, list_count; int i; unsigned char **res_argv = NULL; - uint32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0; + SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0; SILC_LOG_DEBUG(("Start")); tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1647,34 +1655,25 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) silc_buffer_put(client_mode_list, tmp, tmp_len); /* 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(cmd->client, conn, channel_id); + if (!channel) { /* Resolve the channel from server */ - silc_idlist_get_channel_by_id(cmd->client, conn, channel_id, TRUE); - - /* Register pending command callback. After we've received the channel - information we will reprocess this command reply by re-calling this - USERS command reply callback. */ - silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, - NULL, silc_client_command_reply_users, cmd); + silc_client_get_channel_by_id_resolve(cmd->client, conn, channel_id, + silc_client_command_reply_users_cb, + cmd); + silc_free(channel_id); + if (client_id_list) + silc_buffer_free(client_id_list); + if (client_mode_list) + silc_buffer_free(client_mode_list); return; - } else { - channel = (SilcChannelEntry)id_cache->context; - } - - /* Remove old client list from channel. */ - silc_list_start(channel->clients); - while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { - silc_list_del(channel->clients, chu); - silc_free(chu); } /* Cache the received Client ID's and modes. */ for (i = 0; i < list_count; i++) { - uint16 idp_len; - uint32 mode; + SilcUInt16 idp_len; + SilcUInt32 mode; SilcClientID *client_id; - SilcClientEntry client; /* Client ID */ SILC_GET16_MSB(idp_len, client_id_list->data + 2); @@ -1687,15 +1686,17 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) SILC_GET32_MSB(mode, client_mode_list->data); /* Check if we have this client cached already. */ - id_cache = NULL; - silc_idcache_find_by_id_one_ext(conn->client_cache, - (void *)client_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache); - - if (!id_cache || !((SilcClientEntry)id_cache->context)->username || - !((SilcClientEntry)id_cache->context)->realname) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); + if (!client_entry || !client_entry->username || !client_entry->realname) { + if (client_entry) { + if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) { + silc_buffer_pull(client_id_list, idp_len); + silc_buffer_pull(client_mode_list, 4); + continue; + } + client_entry->status |= SILC_CLIENT_STATUS_RESOLVING; + } + /* No we don't have it (or it is incomplete in information), query it from the server. Assemble argument table that will be sent for the WHOIS command later. */ @@ -1710,17 +1711,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) res_argv_types[res_argc] = res_argc + 3; res_argc++; } else { - /* Found the client, join it to the channel */ - client = (SilcClientEntry)id_cache->context; - chu = silc_calloc(1, sizeof(*chu)); - chu->client = client; - chu->mode = mode; - silc_list_add(channel->clients, chu); - - silc_free(client_id); - id_cache = NULL; + if (!silc_client_on_channel(channel, client_entry)) { + chu = silc_calloc(1, sizeof(*chu)); + chu->client = client_entry; + chu->channel = channel; + silc_hash_table_add(channel->user_list, client_entry, chu); + silc_hash_table_add(client_entry->channels, channel, chu); + } } + silc_free(client_id); silc_buffer_pull(client_id_list, idp_len); silc_buffer_pull(client_mode_list, 4); } @@ -1731,9 +1731,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) SilcBuffer res_cmd; /* Send the WHOIS command to server */ + silc_client_command_register(cmd->client, SILC_COMMAND_WHOIS, NULL, NULL, + silc_client_command_reply_whois_i, 0, + ++conn->cmd_ident); res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS, res_argc, res_argv, res_argv_lens, - res_argv_types, ++conn->cmd_ident); + res_argv_types, conn->cmd_ident); silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, res_cmd->data, res_cmd->len, TRUE); @@ -1742,24 +1745,30 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) command reply we will reprocess this command reply by re-calling this USERS command reply callback. */ silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident, - NULL, silc_client_command_reply_users, cmd); + silc_client_command_reply_users, cmd); silc_buffer_free(res_cmd); - if (channel_id) - silc_free(channel_id); - + silc_free(channel_id); silc_free(res_argv); silc_free(res_argv_lens); silc_free(res_argv_types); + if (client_id_list) + silc_buffer_free(client_id_list); + if (client_mode_list) + silc_buffer_free(client_mode_list); return; } + + silc_buffer_push(client_id_list, (client_id_list->data - + client_id_list->head)); + silc_buffer_push(client_mode_list, (client_mode_list->data - + client_mode_list->head)); /* Notify application */ COMMAND_REPLY((ARGS, channel, list_count, client_id_list, client_mode_list)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS); silc_client_command_reply_free(cmd); silc_free(channel_id); if (client_id_list) @@ -1784,8 +1793,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) SilcServerEntry server_entry; SilcSKEPKType type; unsigned char *tmp, *pk; - uint32 len; - uint16 pk_len; + SilcUInt32 len; + SilcUInt16 pk_len; SilcIdType id_type; SilcPublicKey public_key = NULL; @@ -1794,8 +1803,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); if (status != SILC_STATUS_OK) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(status)); + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(status)); COMMAND_REPLY_ERROR; goto out; } @@ -1805,7 +1814,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) COMMAND_REPLY_ERROR; goto out; } - idp = silc_id_payload_parse_data(tmp, len); + idp = silc_id_payload_parse(tmp, len); if (!idp) { COMMAND_REPLY_ERROR; goto out; @@ -1819,32 +1828,21 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) SILC_GET16_MSB(type, tmp + 2); pk = tmp + 4; - if (type != SILC_SKE_PK_TYPE_SILC) { - COMMAND_REPLY_ERROR; - goto out; - } - - if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key)) { - COMMAND_REPLY_ERROR; - goto out; - } + if (type == SILC_SKE_PK_TYPE_SILC) + if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key)) + public_key = NULL; } id_type = silc_id_payload_get_type(idp); if (id_type == SILC_ID_CLIENT) { /* Received client's public key */ client_id = silc_id_payload_get_id(idp); - if (!silc_idcache_find_by_id_one_ext(conn->client_cache, - (void *)client_id, - NULL, NULL, - silc_hash_client_id_compare, NULL, - &id_cache)) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); + if (!client_entry) { COMMAND_REPLY_ERROR; goto out; } - client_entry = (SilcClientEntry)id_cache->context; - /* Notify application */ COMMAND_REPLY((ARGS, id_type, client_entry, public_key)); } else if (id_type == SILC_ID_SERVER) { @@ -1864,7 +1862,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY); - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY); if (idp) silc_id_payload_free(idp); if (public_key) @@ -1873,3 +1870,185 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) silc_free(server_id); silc_client_command_reply_free(cmd); } + +SILC_CLIENT_CMD_REPLY_FUNC(quit) +{ + silc_client_command_reply_free(context); +} + + +/****************************************************************************** + + Internal command reply functions + +******************************************************************************/ + +SILC_CLIENT_CMD_REPLY_FUNC(whois_i) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcCommandStatus status; + + SILC_LOG_DEBUG(("Start")); + + SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); + if (status != SILC_STATUS_OK && + status != SILC_STATUS_LIST_START && + status != SILC_STATUS_LIST_ITEM && + status != SILC_STATUS_LIST_END) + goto out; + + /* Save WHOIS info */ + silc_client_command_reply_whois_save(cmd, status, FALSE); + + /* Pending callbacks are not executed if this was an list entry */ + if (status != SILC_STATUS_OK && + status != SILC_STATUS_LIST_END) { + silc_client_command_reply_free(cmd); + return; + } + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS); + + /* If we received notify for invalid ID we'll remove the ID if we + have it cached. */ + if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { + SilcClientEntry client_entry; + SilcUInt32 tmp_len; + unsigned char *tmp = + silc_argument_get_arg_type(silc_command_get_args(cmd->payload), + 2, &tmp_len); + if (tmp) { + SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len); + if (client_id) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, + client_id); + if (client_entry) + silc_client_del_client(cmd->client, conn, client_entry); + silc_free(client_id); + } + } + } + + /* Unregister this command reply */ + silc_client_command_unregister(cmd->client, SILC_COMMAND_WHOIS, + NULL, silc_client_command_reply_whois_i, + cmd->ident); + + silc_client_command_reply_free(cmd); +} + +SILC_CLIENT_CMD_REPLY_FUNC(identify_i) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcCommandStatus status; + + SILC_LOG_DEBUG(("Start")); + + SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); + if (status != SILC_STATUS_OK && + status != SILC_STATUS_LIST_START && + status != SILC_STATUS_LIST_ITEM && + status != SILC_STATUS_LIST_END) + goto out; + + /* Save IDENTIFY info */ + silc_client_command_reply_identify_save(cmd, status, FALSE); + + /* Pending callbacks are not executed if this was an list entry */ + if (status != SILC_STATUS_OK && + status != SILC_STATUS_LIST_END) { + silc_client_command_reply_free(cmd); + return; + } + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY); + + /* If we received notify for invalid ID we'll remove the ID if we + have it cached. */ + if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { + SilcClientEntry client_entry; + SilcUInt32 tmp_len; + unsigned char *tmp = + silc_argument_get_arg_type(silc_command_get_args(cmd->payload), + 2, &tmp_len); + if (tmp) { + SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len); + if (client_id) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, + client_id); + if (client_entry) + silc_client_del_client(cmd->client, conn, client_entry); + silc_free(client_id); + } + } + } + + /* Unregister this command reply */ + silc_client_command_unregister(cmd->client, SILC_COMMAND_IDENTIFY, + NULL, silc_client_command_reply_identify_i, + cmd->ident); + + silc_client_command_reply_free(cmd); +} + +SILC_CLIENT_CMD_REPLY_FUNC(info_i) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcCommandStatus status; + unsigned char *tmp; + SilcIDCacheEntry id_cache; + SilcServerEntry server; + SilcServerID *server_id = NULL; + char *server_name, *server_info; + SilcUInt32 len; + + SILC_LOG_DEBUG(("Start")); + + tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); + SILC_GET16_MSB(status, tmp); + if (status != SILC_STATUS_OK) + goto out; + + /* Get server ID */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + if (!tmp) + goto out; + + server_id = silc_id_payload_parse_id(tmp, len); + if (!server_id) + goto out; + + /* Get server name */ + server_name = silc_argument_get_arg_type(cmd->args, 3, NULL); + if (!server_name) + goto out; + + /* Get server info */ + server_info = silc_argument_get_arg_type(cmd->args, 4, NULL); + if (!server_info) + goto out; + + /* See whether we have this server cached. If not create it. */ + if (!silc_idcache_find_by_id_one(conn->server_cache, (void *)server_id, + &id_cache)) { + SILC_LOG_DEBUG(("New server entry")); + server = silc_calloc(1, sizeof(*server)); + server->server_name = strdup(server_name); + server->server_info = strdup(server_info); + server->server_id = silc_id_dup(server_id, SILC_ID_SERVER); + + /* Add it to the cache */ + silc_idcache_add(conn->server_cache, server->server_name, + server->server_id, (void *)server, 0, NULL); + } + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO); + silc_free(server_id); + silc_client_command_reply_free(cmd); +}