From: Pekka Riikonen Date: Tue, 10 Jul 2001 20:27:56 +0000 (+0000) Subject: updates. X-Git-Tag: robodoc-323~83 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=6617b351fc8655b8772cae80117faf5b35cc0378 updates. --- diff --git a/CHANGES b/CHANGES index 235f8417..f170b1d9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,75 @@ +Tue Jul 10 18:05:38 EEST 2001 Pekka Riikonen + + * Added SilcServerEntry context into the client library + to represent one server. The INFO command now allocates + these to save the resolved server info. For now on the + client library will also keep information about servers, + connected and resolved with INFO. + + The INFO command now allocates the SilcServerEntry context + and saves the server info there. The COMMAND_REPLY in + the INFO now returns the parameters to application in + same order as defined in the protocol specification. + + The entries are cached in the client->server_cache. + + * The INFO command is now issued after received the Client ID + from the server. Affected file lib/silcclient/client.c. + + * The CMODE_CHANGE notify may now return also an SilcServerEntry + to the application as the mode changer might be server. + It is guaranteed that NULL is not returned anymore to the + application. Affected file lib/silcclient/client_notify.c. + + The ID Type is now also passed to the application so that + it can check whether the returned entry is SilcClientEntry + or SilcServerEntry. + + Added new function silc_client_get_server_by_id to return + the server entry by ID. Affected files are the + lib/silcclient/silcapi.h and lib/silcclient/idlist.c. + + * Do not create the channel in the Irssi SILC Client when issuing + the JOIN command but when received the sucessful JOIN command + reply. Otherwise the channel might get created even though we + could not join it. The Affected file is + irssi/src/silc/core/[silc-channels.c/client_ops.c]. + + * Fixed a channel joining bug in router. The router must also + check the channel modes, invite and ban lists etc. when serving + the JOIN command sent by normal server. Affected file is + silcd/command.c. The router now resolves the client's + information from the server who sent the JOIN command if it + does not know it, and processes the JOIN command only after + that. + + * Changed the SilcCommandCb to take new argument; void *context2. + Affected file lib/silccore/silccommand.h + + The second argument in the command callbacks in the server now + includes the SilcServerCommandReplyContext if the command was + called as pending command callback from the command reply. + Otherwise it is NULL. When called as pending the status of the + command reply will be checked and if it was erronous the + error will be sent to the original sender of the command. + This way the client always receives the error messages even + though the server was actually the one who received the error + when it resent the command to router, for example. Affected + files silcd/command[_reply].[ch]. + + * Fixed sending WHOWAS command's error message to client if + the requested client could not be found. It was missing. + silcd/command.c. + + * Changed the CMODE and CUMODE commands reply arguments in the + protocol specification. The Channel ID is now sent in both + of the commands to identify the channel. Implemented this + new feature to the client and server. Affected files + lib/silcclient/command_reply.c and silcd/command.c. + + * Made better checks for invite and ban lists in the JOIN + command in server. Affected file silcd/command.c. + Mon Jul 9 18:28:34 EEST 2001 Pekka Riikonen * The server now performs the incoming host IP/DNS lookup diff --git a/TODO b/TODO index 745a026b..b6c1447d 100644 --- a/TODO +++ b/TODO @@ -1,23 +1,15 @@ TODO/bugs in Irssi SILC client ============================== - o Do not let irssi update the status bar on JOIN until the join command - is successful, so that it does not update that I'm on the channel - even though I could not join the channel. - - o The CMODE notify handling in client library may return NULL - client entry pointer to the application (when server was the CMODE's - executor). Fix this somehow. - - o Add PERL scripting support from Irssi CVS. + o We should get rid of the clientconfig.[ch] in Irssi SILC and move the + cipher, hash, hmac and pkcs configuration to the Irssi SILC's config + file. o Add local commands to list the current server and client public keys that the user has. And a local command to dump the contents of the public key to the screen. Something like LISTKEYS, SHOWKEY... - o We should get rid of the clientconfig.[ch] in Irssi SILC and move the - cipher, hash, hmac and pkcs configuration to the Irssi SILC's config - file. + o Add PERL scripting support from Irssi CVS. o Extend the /HELP command to support sub commands or something. So that user can say /help set mutual_authentication they would get @@ -30,20 +22,11 @@ TODO/bugs in Irssi SILC client TODO/bugs In SILC Client Library ================================ - o Library should save the cumode and not start from 0 everytime then - CUMODE is issued. A mechanism of getting the channel entry for - CMODE and CUMODE by the command reply identifier must be added. - Otherwise saving the modes for the channels and channel user - entries are impossible since server does not send Channel ID as - command reply in these commands. - o All protocol execution timeouts are hard coded. They should be configurable and the Irssi SILC client should be able to set them with for example /set key_exchange_timeout etc. The silc_client_alloc should take a Params structure or something as argument. - o silc_client_close_connection leaks memory. Read the XXX from code. - o The client library must manage somehow when receiving client that has same nickname, same server, same username but different Client ID than what we have in the cache. It is now assumed that they are different @@ -52,6 +35,8 @@ TODO/bugs In SILC Client Library interface separately or it could just remove the old client unless it is on some channels. + o silc_client_close_connection leaks memory. Read the XXX from code. + TODO/bugs In SILC Server ======================== diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 12fe0f4e..b873e2cb 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -496,11 +496,9 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, client_id_list = va_arg(vp, SilcBuffer); chanrec = silc_channel_find(server, channel); - if (chanrec != NULL && !success) - channel_destroy(CHANNEL(chanrec)); - else if (chanrec == NULL && success) + if (!chanrec) chanrec = silc_channel_create(server, channel, TRUE); - + if (topic) { g_free_not_null(chanrec->topic); chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic); diff --git a/apps/irssi/src/silc/core/silc-channels.c b/apps/irssi/src/silc/core/silc-channels.c index c823e0a5..5bf3383e 100644 --- a/apps/irssi/src/silc/core/silc-channels.c +++ b/apps/irssi/src/silc/core/silc-channels.c @@ -89,7 +89,6 @@ static void silc_channels_join(SILC_SERVER_REC *server, continue; } - silc_channel_create(server, channel, FALSE); silc_command_exec(server, "JOIN", channel); g_free(channel); } @@ -289,12 +288,16 @@ static void event_nick(SILC_SERVER_REC *server, va_list va) static void event_cmode(SILC_SERVER_REC *server, va_list va) { SILC_CHANNEL_REC *chanrec; + void *entry; SilcClientEntry client; + SilcServerEntry server_entry; SilcChannelEntry channel; char *mode; uint32 modei; + SilcIdType idtype; - client = va_arg(va, SilcClientEntry); + idtype = va_arg(va, SilcIdType); + entry = va_arg(va, void *); modei = va_arg(va, uint32); (void)va_arg(va, char *); (void)va_arg(va, char *); @@ -311,10 +314,19 @@ static void event_cmode(SILC_SERVER_REC *server, va_list va) signal_emit("channel mode changed", 1, chanrec); } - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE, - channel->channel_name, mode ? mode : "removed all", - client->nickname); + if (idtype == SILC_ID_CLIENT) { + client = (SilcClientEntry)entry; + printformat_module("fe-common/silc", server, channel->channel_name, + MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE, + channel->channel_name, mode ? mode : "removed all", + client->nickname); + } else { + server_entry = (SilcServerEntry)entry; + printformat_module("fe-common/silc", server, channel->channel_name, + MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE, + channel->channel_name, mode ? mode : "removed all", + server_entry->server_name); + } g_free(mode); } diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index 05c76845..566b269a 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -318,7 +318,7 @@ void silc_command_exec(SILC_SERVER_REC *server, ctx->argv_types = argv_types; /* Execute command */ - (*cmd->cb)(ctx); + (*cmd->cb)(ctx, NULL); } /* Generic command function to call any SILC command directly. */ diff --git a/apps/silcd/command.c b/apps/silcd/command.c index b4c0b530..52a4a78f 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -37,6 +37,10 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd, uint32 arg_type, unsigned char *arg, uint32 arg_len); +static bool +silc_server_command_pending_error_check(SilcServerCommandContext cmd, + SilcServerCommandReplyContext cmdr, + SilcCommand command); SILC_TASK_CALLBACK(silc_server_command_process_timeout); /* Server command list. */ @@ -76,12 +80,25 @@ SilcServerCommand silc_command_list[] = { NULL, 0 }, }; -#define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \ +/* Performs several checks to the command. It first checks whether this + command was called as pending command callback. If it was then it checks + whether error occurred in the command reply where the pending command + callback was called. + + It also checks that the requested command includes correct amount + of arguments. */ +#define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \ do { \ - uint32 _argc = silc_argument_get_arg_num(cmd->args); \ + uint32 _argc; \ \ SILC_LOG_DEBUG(("Start")); \ \ + if (silc_server_command_pending_error_check(cmd, context2, command)) { \ + silc_server_command_free(cmd); \ + return; \ + } \ + \ + _argc = silc_argument_get_arg_num(cmd->args); \ if (_argc < min) { \ silc_server_command_send_status_reply(cmd, command, \ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \ @@ -132,12 +149,12 @@ SILC_TASK_CALLBACK(silc_server_command_process_timeout) client->last_command = time(NULL); if (!(timeout->cmd->flags & SILC_CF_REG)) - timeout->cmd->cb(timeout->ctx); + timeout->cmd->cb(timeout->ctx, NULL); else if (silc_server_is_registered(timeout->ctx->server, timeout->ctx->sock, timeout->ctx, timeout->cmd->cmd)) - timeout->cmd->cb(timeout->ctx); + timeout->cmd->cb(timeout->ctx, NULL); silc_free(timeout); } @@ -226,9 +243,9 @@ void silc_server_command_process(SilcServer server, /* Execute for server */ if (!(cmd->flags & SILC_CF_REG)) - cmd->cb(ctx); + cmd->cb(ctx, NULL); else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) - cmd->cb(ctx); + cmd->cb(ctx, NULL); } /* Allocate Command Context */ @@ -389,6 +406,31 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd, silc_buffer_free(buffer); } +/* This function can be called to check whether in the command reply + an error occurred. This function has no effect if this is called + when the command function was not called as pending command callback. + This returns TRUE if error had occurred. */ + +static bool +silc_server_command_pending_error_check(SilcServerCommandContext cmd, + SilcServerCommandReplyContext cmdr, + SilcCommand command) +{ + SilcCommandStatus status; + + if (!cmd->pending || !cmdr) + return FALSE; + + SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL)); + if (status != SILC_STATUS_OK) { + /* Send the error message */ + silc_server_command_send_status_reply(cmd, command, status); + return TRUE; + } + + return FALSE; +} + /****************************************************************************** WHOIS Functions @@ -919,7 +961,7 @@ SILC_SERVER_CMD_FUNC(whois) SilcServerCommandContext cmd = (SilcServerCommandContext)context; int ret = 0; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328); if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) ret = silc_server_command_whois_from_client(cmd); @@ -1136,8 +1178,8 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd) to our router if we are normal server, so let's do it now unless we are standalone. We will not send any replies to the client until we have received reply from the router. */ - if (server->server_type == SILC_SERVER && - !cmd->pending && !server->standalone) { + if (server->server_type == SILC_SERVER && !cmd->pending && + !server->standalone) { SilcBuffer tmpbuf; uint16 old_ident; @@ -1189,6 +1231,14 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd) nick, server->md5hash, &clients, &clients_count); + if (!clients) { + /* Such a client really does not exist in the SILC network. */ + silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS, + SILC_STATUS_ERR_NO_SUCH_NICK, + 3, nick, strlen(nick)); + goto out; + } + if (!silc_server_command_whowas_check(cmd, clients, clients_count)) { ret = -1; goto out; @@ -1271,7 +1321,7 @@ SILC_SERVER_CMD_FUNC(whowas) SilcServerCommandContext cmd = (SilcServerCommandContext)context; int ret = 0; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2); if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) ret = silc_server_command_whowas_from_client(cmd); @@ -1698,7 +1748,7 @@ SILC_SERVER_CMD_FUNC(identify) SilcServerCommandContext cmd = (SilcServerCommandContext)context; int ret = 0; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328); if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) ret = silc_server_command_identify_from_client(cmd); @@ -1743,7 +1793,7 @@ SILC_SERVER_CMD_FUNC(nick) if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1); /* Check nickname */ nick = silc_argument_get_arg_type(cmd->args, 1, NULL); @@ -1958,7 +2008,7 @@ SILC_SERVER_CMD_FUNC(list) SilcChannelEntry *lchannels = NULL, *gchannels = NULL; uint32 lch_count = 0, gch_count = 0; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 2); /* Get Channel ID */ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); @@ -2004,7 +2054,7 @@ SILC_SERVER_CMD_FUNC(topic) uint32 argc, tmp_len; uint16 ident = silc_command_get_ident(cmd->payload); - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2); argc = silc_argument_get_arg_num(cmd->args); @@ -2130,7 +2180,7 @@ SILC_SERVER_CMD_FUNC(invite) uint32 len; uint16 ident = silc_command_get_ident(cmd->payload); - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4); /* Get Channel ID */ tmp = silc_argument_get_arg_type(cmd->args, 1, &len); @@ -2375,7 +2425,7 @@ SILC_SERVER_CMD_FUNC(quit) unsigned char *tmp = NULL; uint32 len = 0; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1); if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; @@ -2412,7 +2462,7 @@ SILC_SERVER_CMD_FUNC(kill) unsigned char *tmp, *comment; uint32 tmp_len, tmp_len2; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2); if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; @@ -2535,7 +2585,7 @@ SILC_SERVER_CMD_FUNC(info) SilcServerEntry entry = NULL; SilcServerID *server_id = NULL; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2); /* Get server name */ dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL); @@ -2694,7 +2744,7 @@ SILC_SERVER_CMD_FUNC(ping) uint32 len; unsigned char *tmp; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2); /* Get Server ID */ tmp = silc_argument_get_arg_type(cmd->args, 1, &len); @@ -2742,7 +2792,7 @@ static void silc_server_command_join_channel(SilcServer server, SilcChannelClientEntry chl; SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list; uint16 ident = silc_command_get_ident(cmd->payload); - char check[512]; + char check[512], check2[512]; SILC_LOG_DEBUG(("Start")); @@ -2753,35 +2803,55 @@ static void silc_server_command_join_channel(SilcServer server, if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) { client = (SilcClientEntry)sock->user_data; } else { - client = silc_idlist_find_client_by_id(server->local_list, client_id, - NULL); - if (!client) - goto out; + client = silc_server_get_client_resolve(server, client_id); + if (!client) { + if (cmd->pending) + goto out; + + /* The client info is being resolved. Reprocess this packet after + receiving the reply to the query. */ + silc_server_command_pending(server, SILC_COMMAND_WHOIS, + server->cmd_ident, NULL, + silc_server_command_join, + silc_server_command_dup(cmd)); + cmd->pending = TRUE; + return; + } + + cmd->pending = FALSE; } /* * Check channel modes */ - if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) { - strncat(check, client->nickname, strlen(client->nickname)); - if (!strchr(client->nickname, '@')) { - strncat(check, "@", 1); - strncat(check, server->server_name, strlen(server->server_name)); - } - strncat(check, "!", 1); - strncat(check, client->username, strlen(client->username)); - if (!strchr(client->username, '@')) { - strncat(check, "@", 1); - strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname)); - } + memset(check, 0, sizeof(check)); + memset(check2, 0, sizeof(check2)); + strncat(check, client->nickname, strlen(client->nickname)); + strncat(check, "!", 1); + strncat(check, client->username, strlen(client->username)); + if (!strchr(client->username, '@')) { + strncat(check, "@", 1); + strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname)); + } + + strncat(check2, client->nickname, strlen(client->nickname)); + if (!strchr(client->nickname, '@')) { + strncat(check2, "@", 1); + strncat(check2, server->server_name, strlen(server->server_name)); + } + strncat(check2, "!", 1); + strncat(check2, client->username, strlen(client->username)); + if (!strchr(client->username, '@')) { + strncat(check2, "@", 1); + strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname)); } /* Check invite list if channel is invite-only channel */ - if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && - channel->mode & SILC_CHANNEL_MODE_INVITE) { + if (channel->mode & SILC_CHANNEL_MODE_INVITE) { if (!channel->invite_list || - !silc_string_match(channel->invite_list, check)) { + (!silc_string_match(channel->invite_list, check) && + !silc_string_match(channel->invite_list, check2))) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, SILC_STATUS_ERR_NOT_INVITED); goto out; @@ -2791,8 +2861,9 @@ static void silc_server_command_join_channel(SilcServer server, /* Check ban list if it exists. If the client's nickname, server, username and/or hostname is in the ban list the access to the channel is denied. */ - if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) { - if (silc_string_match(channel->ban_list, check)) { + if (channel->ban_list) { + if (silc_string_match(channel->ban_list, check) || + silc_string_match(channel->ban_list, check2)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, SILC_STATUS_ERR_BANNED_FROM_CHANNEL); goto out; @@ -2953,7 +3024,7 @@ SILC_SERVER_CMD_FUNC(join) int created = FALSE; SilcClientID *client_id; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4); /* Get channel name */ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); @@ -2970,7 +3041,6 @@ SILC_SERVER_CMD_FUNC(join) if (silc_server_command_bad_chars(channel_name) == TRUE) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, SILC_STATUS_ERR_BAD_CHANNEL); - silc_free(channel_name); goto out; } @@ -3034,6 +3104,12 @@ SILC_SERVER_CMD_FUNC(join) if (server->server_type == SILC_SERVER) { SilcBuffer tmpbuf; uint16 old_ident; + + /* If this is pending command callback then we've resolved + it and it didn't work, return since we've notified the + client already in the command reply callback. */ + if (cmd->pending) + goto out; old_ident = silc_command_get_ident(cmd->payload); silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng)); @@ -3135,7 +3211,7 @@ SILC_SERVER_CMD_FUNC(motd) uint32 motd_len; uint16 ident = silc_command_get_ident(cmd->payload); - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1); /* Get server name */ dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL); @@ -3282,7 +3358,7 @@ SILC_SERVER_CMD_FUNC(umode) if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2); /* Get the client's mode mask */ tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL); @@ -3430,7 +3506,7 @@ SILC_SERVER_CMD_FUNC(cmode) uint32 mode_mask, tmp_len, tmp_len2; uint16 ident = silc_command_get_ident(cmd->payload); - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7); /* Get Channel ID */ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2); @@ -3744,8 +3820,9 @@ SILC_SERVER_CMD_FUNC(cmode) /* Send command reply to sender */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE, - SILC_STATUS_OK, ident, 1, - 2, tmp_mask, 4); + SILC_STATUS_OK, ident, 2, + 2, tmp_id, tmp_len2, + 3, tmp_mask, 4); silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, packet->data, packet->len, FALSE); @@ -3776,7 +3853,7 @@ SILC_SERVER_CMD_FUNC(cumode) int notify = FALSE; uint16 ident = silc_command_get_ident(cmd->payload); - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4); /* Get Channel ID */ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len); @@ -3986,9 +4063,10 @@ SILC_SERVER_CMD_FUNC(cumode) /* Send command reply to sender */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE, - SILC_STATUS_OK, ident, 2, + SILC_STATUS_OK, ident, 3, 2, tmp_mask, 4, - 3, tmp_id, tmp_len); + 3, tmp_ch_id, tmp_ch_len, + 4, tmp_id, tmp_len); silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, packet->data, packet->len, FALSE); @@ -4017,7 +4095,7 @@ SILC_SERVER_CMD_FUNC(kick) uint32 tmp_len; unsigned char *tmp, *comment; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3); /* Get Channel ID */ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); @@ -4160,7 +4238,7 @@ SILC_SERVER_CMD_FUNC(oper) SilcServerConfigSectionAdminConnection *admin; SilcIDListData idata = (SilcIDListData)client; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2); if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; @@ -4232,7 +4310,7 @@ SILC_SERVER_CMD_FUNC(silcoper) SilcServerConfigSectionAdminConnection *admin; SilcIDListData idata = (SilcIDListData)client; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2); if (server->server_type == SILC_SERVER) goto out; @@ -4306,7 +4384,7 @@ SILC_SERVER_CMD_FUNC(connect) uint32 tmp_len; uint32 port = SILC_PORT; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2); if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; @@ -4368,7 +4446,7 @@ SILC_SERVER_CMD_FUNC(ban) if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3); /* Get Channel ID */ id = silc_argument_get_arg_type(cmd->args, 1, &id_len); @@ -4496,7 +4574,7 @@ SILC_SERVER_CMD_FUNC(close) unsigned char *name; uint32 port = SILC_PORT; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2); if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; @@ -4551,7 +4629,7 @@ SILC_SERVER_CMD_FUNC(shutdown) SilcServer server = cmd->server; SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0); if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; @@ -4588,7 +4666,7 @@ SILC_SERVER_CMD_FUNC(leave) uint32 len; unsigned char *tmp; - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2); /* Get Channel ID */ tmp = silc_argument_get_arg_type(cmd->args, 1, &len); @@ -4673,7 +4751,7 @@ SILC_SERVER_CMD_FUNC(users) uint32 list_count = 0; uint16 ident = silc_command_get_ident(cmd->payload); - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1); + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 1); /* Get Channel ID */ channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len); diff --git a/apps/silcd/command.h b/apps/silcd/command.h index 4134ee2e..7d884e16 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -85,15 +85,21 @@ typedef struct SilcServerCommandPendingStruct { #define SILC_SERVER_CMD(func, cmd, flags) \ { silc_server_command_##func, SILC_COMMAND_##cmd, flags } -/* Macro used to declare command functions */ +/* Macro used to declare command functions. The `context' will be the + SilcServerCommandContext and the `context2' is the + SilcServerCommandReplyContext if this function is called from the + command reply as pending command callback. Otherwise `context2' + is NULL. */ #define SILC_SERVER_CMD_FUNC(func) \ -void silc_server_command_##func(void *context) - -/* Executed pending command */ -#define SILC_SERVER_PENDING_EXEC(ctx, cmd) \ -do { \ - if (ctx->callback) \ - (*ctx->callback)(ctx->context); \ +void silc_server_command_##func(void *context, void *context2) + +/* Executed pending command. The first argument to the callback function + is the user specified context. The second argument is always the + SilcServerCommandReply context. */ +#define SILC_SERVER_PENDING_EXEC(ctx, cmd) \ +do { \ + if (ctx->callback) \ + (*ctx->callback)(ctx->context, ctx); \ } while(0) /* Execute destructor for pending command */ diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 4717e3b7..a012aa8c 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -107,7 +107,7 @@ void silc_server_command_reply_process(SilcServer server, return; } - cmd->cb(ctx); + cmd->cb(ctx, NULL); } /* Free command reply context and its internals. */ diff --git a/apps/silcd/command_reply.h b/apps/silcd/command_reply.h index 213ed979..75be5094 100644 --- a/apps/silcd/command_reply.h +++ b/apps/silcd/command_reply.h @@ -54,7 +54,7 @@ typedef struct { /* Macro used to declare command reply functions */ #define SILC_SERVER_CMD_REPLY_FUNC(func) \ -void silc_server_command_reply_##func(void *context) +void silc_server_command_reply_##func(void *context, void *context2) /* Prototypes */ void silc_server_command_reply_free(SilcServerCommandReplyContext cmd); diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index abcfb9f1..4e5f5272 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -144,6 +144,8 @@ silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id, if (ret_entry) *ret_entry = id_cache; + SILC_LOG_DEBUG(("Found")); + return server; } diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 707e1d2d..38f645e4 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -3834,6 +3834,7 @@ SilcClientEntry silc_server_get_client_resolve(SilcServer server, buffer->data, buffer->len, FALSE); silc_buffer_free(idp); silc_buffer_free(buffer); + return NULL; } return client; diff --git a/doc/draft-riikonen-silc-commands-01.nroff b/doc/draft-riikonen-silc-commands-01.nroff index bf1aa600..c03fd192 100644 --- a/doc/draft-riikonen-silc-commands-01.nroff +++ b/doc/draft-riikonen-silc-commands-01.nroff @@ -1163,8 +1163,9 @@ List of all defined commands in SILC follows. Reply messages to the command: - Max Arguments: 2 - Arguments: (1) (2) + Max Arguments: 3 + Arguments: (1) (2) + (3) This command replies with the changed channel mode mask that client MUST keep locally. @@ -1230,12 +1231,13 @@ List of all defined commands in SILC follows. Reply messages to the command: - Max Arguments: 3 + Max Arguments: 4 Arguments: (1) (2) - (3) + (3) (4) This command replies with the changed channel user mode mask that - client MUST keep locally. The is the target client. + client MUST keep locally. The is the specified + channel. The is the target client. Status messages: diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 20c87870..2f857a1f 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -1262,6 +1262,7 @@ void silc_client_receive_new_id(SilcClient client, { SilcClientConnection conn = (SilcClientConnection)sock->user_data; int connecting = FALSE; + SilcBuffer sidp; if (!conn->local_entry) connecting = TRUE; @@ -1299,6 +1300,13 @@ void silc_client_receive_new_id(SilcClient client, silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, (void *)conn->local_entry, FALSE); + /* Issue INFO command to fetch the real server name and server information + and other stuff. */ + sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER); + silc_client_send_command(client, conn, SILC_COMMAND_INFO, + ++conn->cmd_ident, 1, 2, sidp->data, sidp->len); + silc_buffer_free(sidp); + /* Notify application of successful connection. We do it here now that we've received the Client ID and are allowed to send traffic. */ if (connecting) diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index 44ae2fbe..f03a2007 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -29,7 +29,7 @@ is required before processing the notify message. This calls again the silc_client_notify_by_server and reprocesses the original notify packet. */ -static void silc_client_notify_by_server_pending(void *context) +static void silc_client_notify_by_server_pending(void *context, void *context2) { SilcPacketContext *p = (SilcPacketContext *)context; silc_client_notify_by_server(p->context, p->sock, p); @@ -79,10 +79,12 @@ void silc_client_notify_by_server(SilcClient client, SilcIDPayload idp; SilcClientID *client_id = NULL; SilcChannelID *channel_id = NULL; + SilcServerID *server_id = NULL; SilcClientEntry client_entry; SilcClientEntry client_entry2; SilcChannelEntry channel; SilcChannelUser chu; + SilcServerEntry server; SilcIDCacheEntry id_cache = NULL; unsigned char *tmp; uint32 tmp_len, mode; @@ -441,26 +443,45 @@ void silc_client_notify_by_server(SilcClient client, goto out; } } else { - client_entry = NULL; + server_id = silc_id_payload_parse_id(tmp, tmp_len); + if (!server_id) { + silc_id_payload_free(idp); + goto out; + } + + server = silc_client_get_server_by_id(client, conn, server_id); + if (!server) { + silc_id_payload_free(idp); + silc_free(server_id); + goto out; + } + + /* Save the pointer to the client_entry pointer */ + client_entry = (SilcClientEntry)server; + silc_free(server_id); } - silc_id_payload_free(idp); - /* Get the mode */ tmp = silc_argument_get_arg_type(args, 2, &tmp_len); - if (!tmp) + if (!tmp) { + silc_id_payload_free(idp); goto out; + } SILC_GET32_MSB(mode, tmp); /* Get channel entry */ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL); - if (!channel_id) + if (!channel_id) { + silc_id_payload_free(idp); goto out; + } if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - &id_cache)) - break; + &id_cache)) { + silc_id_payload_free(idp); + goto out; + } channel = (SilcChannelEntry)id_cache->context; @@ -487,8 +508,10 @@ void silc_client_notify_by_server(SilcClient client, /* 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. */ - client->ops->notify(client, conn, type, client_entry, mode, NULL, - tmp, channel); + client->ops->notify(client, conn, type, silc_id_payload_get_type(idp), + client_entry, mode, NULL, tmp, channel); + + silc_id_payload_free(idp); break; case SILC_NOTIFY_TYPE_CUMODE_CHANGE: diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index ce57cdba..3e6839fa 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -752,7 +752,8 @@ SILC_CLIENT_CMD_FUNC(kill) /* Parse the typed nickname. */ if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Bad nickname"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Bad nickname"); COMMAND_ERROR; goto out; } diff --git a/lib/silcclient/command.h b/lib/silcclient/command.h index 69a94efd..10218167 100644 --- a/lib/silcclient/command.h +++ b/lib/silcclient/command.h @@ -101,13 +101,13 @@ extern SilcClientCommandPending *silc_command_pending; /* Macro used to declare command functions */ #define SILC_CLIENT_CMD_FUNC(func) \ -void silc_client_command_##func(void *context) +void silc_client_command_##func(void *context, void *context2) /* Executed pending command callback */ #define SILC_CLIENT_PENDING_EXEC(ctx, cmd) \ do { \ if ((ctx)->callback) \ - (*ctx->callback)(ctx->context); \ + (*ctx->callback)(ctx->context, ctx); \ } while(0) /* Execute destructor for pending command */ diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 1fa5d5a5..b36e5446 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -168,7 +168,7 @@ void silc_client_command_reply_process(SilcClient client, return; } - cmd->cb(ctx); + cmd->cb(ctx, NULL); } /* Returns status message string */ @@ -800,9 +800,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; - SilcClient client = cmd->client; SilcCommandStatus status; unsigned char *tmp; + SilcIDCacheEntry id_cache; + SilcServerEntry server; + SilcServerID *server_id = NULL; + char *server_name, *server_info; + uint32 len; tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); @@ -816,32 +820,50 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) } /* Get server ID */ - tmp = silc_argument_get_arg_type(cmd->args, 2, NULL); + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); if (!tmp) goto out; - /* XXX save server id */ + server_id = silc_id_payload_parse_id(tmp, len); + if (!server_id) + goto out; /* Get server name */ - tmp = silc_argument_get_arg_type(cmd->args, 3, NULL); - if (!tmp) + server_name = silc_argument_get_arg_type(cmd->args, 3, NULL); + if (!server_name) goto out; /* Get server info */ - tmp = silc_argument_get_arg_type(cmd->args, 4, NULL); - if (!tmp) + server_info = silc_argument_get_arg_type(cmd->args, 4, NULL); + if (!server_info) goto out; - client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "Info: %s", tmp); + /* 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, FALSE); + } else { + server = (SilcServerEntry)id_cache->context; + } + /* Notify application */ - COMMAND_REPLY((ARGS, NULL, (char *)tmp)); + COMMAND_REPLY((ARGS, server, server->server_name, server->server_info)); /* Execute any pending command callbacks */ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO); out: + if (server_id) + silc_free(server_id); SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO); silc_client_command_reply_free(cmd); } @@ -1210,6 +1232,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) SilcCommandStatus status; unsigned char *tmp; uint32 mode; + SilcIDCacheEntry id_cache; + SilcChannelID *channel_id; + SilcChannelEntry channel; + uint32 len; SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); if (status != SILC_STATUS_OK) { @@ -1219,17 +1245,39 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) goto out; } + /* Take Channel ID */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + if (!tmp) + goto out; + channel_id = silc_id_payload_parse_id(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)) { + 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, 2, NULL); + tmp = silc_argument_get_arg_type(cmd->args, 3, NULL); if (!tmp) { + silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } + /* Save the mode */ SILC_GET32_MSB(mode, tmp); + channel->mode = mode; /* Notify application */ - COMMAND_REPLY((ARGS, mode)); + COMMAND_REPLY((ARGS, channel, mode)); + silc_free(channel_id); /* Execute any pending command callbacks */ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CMODE); @@ -1248,6 +1296,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) SilcCommandStatus status; SilcIDCacheEntry id_cache = NULL; SilcClientID *client_id; + SilcChannelID *channel_id; + SilcClientEntry client_entry; + SilcChannelEntry channel; + SilcChannelUser chu; unsigned char *tmp, *id; uint32 len, mode; @@ -1266,14 +1318,34 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) goto out; } + /* Take Channel ID */ + tmp = silc_argument_get_arg_type(cmd->args, 3, &len); + if (!tmp) + goto out; + channel_id = silc_id_payload_parse_id(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)) { + 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, 3, &len); + id = silc_argument_get_arg_type(cmd->args, 4, &len); if (!id) { + silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } client_id = silc_id_payload_parse_id(id, len); if (!client_id) { + silc_free(channel_id); COMMAND_REPLY_ERROR; goto out; } @@ -1283,15 +1355,27 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) NULL, NULL, silc_hash_client_id_compare, NULL, &id_cache)) { + 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, tmp); + while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { + if (chu->client == client_entry) { + chu->mode = mode; + break; + } + } /* Notify application */ - COMMAND_REPLY((ARGS, mode, (SilcClientEntry)id_cache->context)); + COMMAND_REPLY((ARGS, mode, channel, client_entry)); silc_free(client_id); + silc_free(channel_id); /* Execute any pending command callbacks */ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CUMODE); diff --git a/lib/silcclient/command_reply.h b/lib/silcclient/command_reply.h index 8c3951a4..1c50430f 100644 --- a/lib/silcclient/command_reply.h +++ b/lib/silcclient/command_reply.h @@ -53,7 +53,7 @@ typedef struct { /* Macro used to declare command reply functions */ #define SILC_CLIENT_CMD_REPLY_FUNC(func) \ -void silc_client_command_reply_##func(void *context) +void silc_client_command_reply_##func(void *context, void *context2) /* Status message structure. Messages are defined below. */ typedef struct { diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index ea45f108..6d865882 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -101,7 +101,7 @@ void silc_client_get_clients(SilcClient client, i->context = context; /* Call the command */ - ctx->command->cb(ctx); + ctx->command->cb(ctx, NULL); /* Add pending callback */ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, @@ -338,7 +338,7 @@ void silc_client_get_clients_by_list(SilcClient client, client_id_list->head); /* We have the clients in cache, get them and call the completion */ - silc_client_command_get_clients_list_callback((void *)in); + silc_client_command_get_clients_list_callback((void *)in, NULL); } /* The old style function to find client entry. This is used by the @@ -377,7 +377,7 @@ SilcClientEntry silc_idlist_get_client(SilcClient client, snprintf(ident, sizeof(ident), "IDENTIFY %s", nickname); silc_parse_command_line(ident, &ctx->argv, &ctx->argv_lens, &ctx->argv_types, &ctx->argc, 2); - ctx->command->cb(ctx); + ctx->command->cb(ctx, NULL); if (list) silc_idcache_list_free(list); @@ -555,3 +555,21 @@ SilcChannelEntry silc_client_get_channel(SilcClient client, return entry; } + +/* Finds entry for server by the server ID. */ + +SilcServerEntry silc_client_get_server_by_id(SilcClient client, + SilcClientConnection conn, + SilcServerID *server_id) +{ + SilcIDCacheEntry id_cache; + SilcServerEntry entry; + + if (!silc_idcache_find_by_id_one(conn->server_cache, (void *)server_id, + &id_cache)) + return NULL; + + entry = (SilcServerEntry)id_cache->context; + + return entry; +} diff --git a/lib/silcclient/idlist.h b/lib/silcclient/idlist.h index b0de7700..835da1aa 100644 --- a/lib/silcclient/idlist.h +++ b/lib/silcclient/idlist.h @@ -25,7 +25,7 @@ (it receives its ID, for example, by IDENTIFY request) we create new client entry. This entry also includes the private message keys if they are used. */ -typedef struct SilcClientEntryStruct { +typedef struct { char *nickname; /* nickname */ char *username; /* username[@host] */ char *server; /* SILC server name */ @@ -79,6 +79,15 @@ typedef struct SilcChannelEntryStruct { SilcChannelPrivateKey curr_key; /* Current private key */ } *SilcChannelEntry; +/* Server entry context. This represents one server. When server information + is resolved with INFO command the server info is saved in this context. + Also the connected servers are saved here. */ +typedef struct { + char *server_name; + char *server_info; + SilcServerID *server_id; +} *SilcServerEntry; + /* Prototypes (some functions are defined in the silcapi.h) */ SilcClientEntry silc_idlist_get_client(SilcClient client, diff --git a/lib/silcclient/silcapi.h b/lib/silcclient/silcapi.h index 5f60e182..140f2f22 100644 --- a/lib/silcclient/silcapi.h +++ b/lib/silcclient/silcapi.h @@ -829,6 +829,24 @@ SilcChannelEntry silc_client_get_channel(SilcClient client, SilcClientConnection conn, char *channel); +/****f* silcclient/SilcClientAPI/silc_client_get_server_by_id + * + * SYNOPSIS + * + * SilcServerEntry silc_client_get_server_by_id(SilcClient client, + * SilcClientConnection conn, + * SilcServerID *server_id); + * + * DESCRIPTION + * + * Finds entry for server by the server ID. Returns the entry or NULL + * if the entry was not found. + * + ***/ +SilcServerEntry silc_client_get_server_by_id(SilcClient client, + SilcClientConnection conn, + SilcServerID *server_id); + /* Command management (command.c) */ diff --git a/lib/silccore/silccommand.h b/lib/silccore/silccommand.h index eeda5a8c..c298d762 100644 --- a/lib/silccore/silccommand.h +++ b/lib/silccore/silccommand.h @@ -35,16 +35,18 @@ * * SYNOPSIS * - * SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer); + * typedef void (*SilcCommandCb)(void *context, void *context2); * * DESCRIPTION * * Command function callback. The actual command function pointer. * This is generic command callback that the application may choose to - * use with its command routines. + * use with its command routines. However, none of the generic + * routines depend on this callback so application may freely define + * their own command callback if desired. * ***/ -typedef void (*SilcCommandCb)(void *context); +typedef void (*SilcCommandCb)(void *context, void *context2); /****s* silccore/SilcCommandAPI/SilcCommandPayload *