X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fcommand_reply.c;h=0ae2890bf8c233eee94188c01c2014e99e75a909;hp=85609d337d0db7c21173c9f91208d93c359e9d22;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=275e2f50c1cbe4a0eec582cf490ef485049541af diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 85609d33..0ae2890b 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -36,61 +36,39 @@ #include "silcclient.h" #include "client_internal.h" -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), "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" }, - { STAT(WILDCARDS), "Unknown command" }, - { STAT(NO_CLIENT_ID), "No Client ID given" }, - { STAT(NO_CHANNEL_ID), "No Channel ID given" }, - { STAT(NO_SERVER_ID), "No Server ID given" }, - { STAT(BAD_CLIENT_ID), "Bad Client ID" }, - { STAT(BAD_CHANNEL_ID), "Bad Channel ID" }, - { STAT(NO_SUCH_CLIENT_ID), "There is no such client" }, - { STAT(NO_SUCH_CHANNEL_ID),"There is no such channel" }, - { STAT(NICKNAME_IN_USE), "Nickname already exists" }, - { STAT(NOT_ON_CHANNEL), "You are not on that channel" }, - { STAT(USER_NOT_ON_CHANNEL),"They are not on the channel" }, - { STAT(USER_ON_CHANNEL), "User already on the channel" }, - { STAT(NOT_REGISTERED), "You have not registered" }, - { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" }, - { STAT(TOO_MANY_PARAMS), "Too many parameters" }, - { STAT(PERM_DENIED), "Permission denied" }, - { STAT(BANNED_FROM_SERVER),"You are banned from this server" }, - { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" }, - { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" }, - { STAT(NOT_INVITED), "Cannot join channel. You have not been invited" }, - { STAT(BANNED_FROM_CHANNEL), "Cannot join channel. You have been banned" }, - { STAT(UNKNOWN_MODE), "Unknown mode" }, - { STAT(NOT_YOU), "Cannot change mode for other users" }, - { STAT(NO_CHANNEL_PRIV), "Permission denied. You are not channel operator" }, - { STAT(NO_CHANNEL_FOPRIV),"Permission denied. You are not channel founder" }, - { STAT(NO_SERVER_PRIV), "Permission denied. You are not server operator" }, - { STAT(NO_ROUTER_PRIV), "Permission denied. You are not SILC operator" }, - { STAT(BAD_NICKNAME), "Bad nickname" }, - { STAT(BAD_CHANNEL), "Bad channel name" }, - { STAT(AUTH_FAILED), "Authentication failed" }, - { STAT(UNKNOWN_ALGORITHM), "Unsupported algorithm" }, - { STAT(NO_SUCH_SERVER_ID), "No such Server ID" }, - - { 0, NULL } -}; - #define SAY cmd->client->internal->ops->say /* All functions that call the COMMAND_CHECK_STATUS macro must have - out: goto label. */ + out: and err: goto labels. out label should call the pending + command replies, and the err label just handle error condition. */ #define COMMAND_CHECK_STATUS \ do { \ SILC_LOG_DEBUG(("Start")); \ if (!silc_command_get_status(cmd->payload, NULL, NULL)) { \ + if (SILC_STATUS_IS_ERROR(cmd->status)) { \ + /* Single error */ \ + COMMAND_REPLY_ERROR; \ + goto out; \ + } \ + /* List of errors */ \ COMMAND_REPLY_ERROR; \ - goto out; \ + if (cmd->status == SILC_STATUS_LIST_END) \ + goto out; \ + goto err; \ + } \ +} while(0) + +/* Same as COMMAND_CHECK_STATUS but doesn't call client operation */ +#define COMMAND_CHECK_STATUS_I \ +do { \ + SILC_LOG_DEBUG(("Start")); \ + if (!silc_command_get_status(cmd->payload, NULL, NULL)) { \ + if (SILC_STATUS_IS_ERROR(cmd->status)) \ + goto out; \ + if (cmd->status == SILC_STATUS_LIST_END) \ + goto out; \ + goto err; \ } \ } while(0) @@ -118,6 +96,7 @@ void silc_client_command_reply_process(SilcClient client, /* Allocate command reply context. This must be free'd by the command reply routine receiving it. */ ctx = silc_calloc(1, sizeof(*ctx)); + ctx->users++; ctx->client = client; ctx->sock = sock; ctx->payload = payload; @@ -127,9 +106,10 @@ void silc_client_command_reply_process(SilcClient client, silc_command_get_status(ctx->payload, &ctx->status, &ctx->error); /* Check for pending commands and mark to be exeucted */ - silc_client_command_pending_check(sock->user_data, ctx, - silc_command_get(ctx->payload), - ctx->ident); + ctx->callbacks = + silc_client_command_pending_check(sock->user_data, ctx, + silc_command_get(ctx->payload), + ctx->ident, &ctx->callbacks_count); /* Execute command reply */ @@ -155,28 +135,26 @@ void silc_client_command_reply_process(SilcClient client, } } -/* Returns status message string */ +/* Duplicate Command Reply Context by adding reference counter. The context + won't be free'd untill it hits zero. */ -char *silc_client_command_status_message(SilcCommandStatus status) +SilcClientCommandReplyContext +silc_client_command_reply_dup(SilcClientCommandReplyContext cmd) { - int i; - - for (i = 0; silc_command_status_messages[i].message; i++) { - if (silc_command_status_messages[i].status == status) - break; - } - - if (silc_command_status_messages[i].message == NULL) - return NULL; - - return silc_command_status_messages[i].message; + cmd->users++; + SILC_LOG_DEBUG(("Command reply context %p refcnt %d->%d", cmd, + cmd->users - 1, cmd->users)); + return cmd; } /* Free command reply context and its internals. */ void silc_client_command_reply_free(SilcClientCommandReplyContext cmd) { - if (cmd) { + cmd->users--; + SILC_LOG_DEBUG(("Command reply context %p refcnt %d->%d", cmd, + cmd->users + 1, cmd->users)); + if (cmd->users < 1) { silc_command_payload_free(cmd->payload); silc_free(cmd); } @@ -184,7 +162,7 @@ void silc_client_command_reply_free(SilcClientCommandReplyContext cmd) static void silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, - SilcCommandStatus status, + SilcStatus status, bool notify) { SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; @@ -195,7 +173,8 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, char *nickname = NULL, *username = NULL; char *realname = NULL; SilcUInt32 idle = 0, mode = 0; - SilcBufferStruct channels; + SilcBufferStruct channels, ch_user_modes; + bool has_channels = FALSE, has_user_modes = FALSE; unsigned char *fingerprint; SilcUInt32 fingerprint_len; @@ -223,8 +202,10 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, } tmp = silc_argument_get_arg_type(cmd->args, 6, &len); - if (tmp) + if (tmp) { silc_buffer_set(&channels, tmp, len); + has_channels = TRUE; + } tmp = silc_argument_get_arg_type(cmd->args, 7, &len); if (tmp) @@ -236,6 +217,12 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, fingerprint = silc_argument_get_arg_type(cmd->args, 9, &fingerprint_len); + tmp = silc_argument_get_arg_type(cmd->args, 10, &len); + if (tmp) { + silc_buffer_set(&ch_user_modes, tmp, len); + has_user_modes = TRUE; + } + /* Check if we have this client cached already. */ client_entry = silc_client_get_client_by_id(cmd->client, conn, client_id); if (!client_entry) { @@ -254,13 +241,22 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, client_entry->fingerprint_len = fingerprint_len; } - if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) - client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; + /* Take Requested Attributes if set. */ + tmp = silc_argument_get_arg_type(cmd->args, 11, &len); + if (tmp) { + if (client_entry->attrs) + silc_attribute_payload_list_free(client_entry->attrs); + client_entry->attrs = silc_attribute_payload_parse(tmp, len); + } + + client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; /* Notify application */ - if (!cmd->callback && notify) - COMMAND_REPLY((ARGS, client_entry, nickname, username, realname, - &channels, mode, idle, fingerprint)); + if (!cmd->callbacks_count && notify) + COMMAND_REPLY((SILC_ARGS, client_entry, nickname, username, realname, + has_channels ? &channels : NULL, mode, idle, + fingerprint, has_user_modes ? &ch_user_modes : NULL, + client_entry->attrs)); } /* Received reply for WHOIS command. This maybe called several times @@ -286,6 +282,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS); + err: /* If we received notify for invalid ID we'll remove the ID if we have it cached. */ if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { @@ -351,7 +348,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas) /* Notify application. We don't save any history information to any cache. Just pass the data to the application for displaying on the screen. */ - COMMAND_REPLY((ARGS, client_entry, nickname, username, realname)); + COMMAND_REPLY((SILC_ARGS, client_entry, nickname, username, realname)); /* Pending callbacks are not executed if this was an list entry */ if (cmd->status != SILC_STATUS_OK && @@ -362,12 +359,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS); + err: silc_client_command_reply_free(cmd); } static void silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, - SilcCommandStatus status, + SilcStatus status, bool notify) { SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; @@ -420,12 +418,11 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, name, info, NULL, 0); } - if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) - client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; + client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; /* Notify application */ if (notify) - COMMAND_REPLY((ARGS, client_entry, name, info)); + COMMAND_REPLY((SILC_ARGS, client_entry, name, info)); break; case SILC_ID_SERVER: @@ -444,11 +441,15 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, COMMAND_REPLY_ERROR; return; } + } else { + silc_client_update_server(client, conn, server_entry, name, info); } + server_entry->resolve_cmd_ident = 0; + /* Notify application */ if (notify) - COMMAND_REPLY((ARGS, server_entry, name, info)); + COMMAND_REPLY((SILC_ARGS, server_entry, name, info)); break; case SILC_ID_CHANNEL: @@ -470,7 +471,7 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, /* Notify application */ if (notify) - COMMAND_REPLY((ARGS, channel_entry, name, info)); + COMMAND_REPLY((SILC_ARGS, channel_entry, name, info)); break; } @@ -504,6 +505,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY); + err: /* If we received notify for invalid ID we'll remove the ID if we have it cached. */ if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { @@ -543,13 +545,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "Cannot set nickname: %s", - silc_client_command_status_message(cmd->error)); + silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } argc = silc_argument_get_arg_num(cmd->args); - if (argc < 2 || argc > 2) { + if (argc < 2 || argc > 3) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "Cannot set nickname: bad reply to command"); COMMAND_REPLY_ERROR; @@ -564,12 +566,23 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick) goto out; } silc_client_receive_new_id(cmd->client, cmd->sock, idp); + + /* Take the new nickname too */ + tmp = silc_argument_get_arg_type(cmd->args, 3, &len); + if (tmp) { + silc_idcache_del_by_context(conn->internal->client_cache, + conn->local_entry); + if (conn->nickname) + silc_free(conn->nickname); + conn->nickname = strdup(tmp); + conn->local_entry->nickname = conn->nickname; + silc_client_nickname_format(cmd->client, conn, conn->local_entry); + silc_idcache_add(conn->internal->client_cache, strdup(tmp), + conn->local_entry->id, conn->local_entry, 0, NULL); + } /* Notify application */ - SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK); - COMMAND_REPLY((ARGS, conn->local_entry)); - silc_client_command_reply_free(cmd); - return; + COMMAND_REPLY((SILC_ARGS, conn->local_entry, conn->local_entry->nickname)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK); @@ -627,7 +640,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(list) } /* Notify application */ - COMMAND_REPLY((ARGS, channel_entry, name, topic, usercount)); + COMMAND_REPLY((SILC_ARGS, channel_entry, name, topic, usercount)); /* Pending callbacks are not executed if this was an list entry */ if (cmd->status != SILC_STATUS_OK && @@ -639,6 +652,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(list) out: silc_free(channel_id); SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LIST); + err: silc_client_command_reply_free(cmd); } @@ -656,7 +670,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -690,7 +704,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic) } /* Notify application */ - COMMAND_REPLY((ARGS, channel, topic)); + COMMAND_REPLY((SILC_ARGS, channel, topic)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_TOPIC); @@ -707,10 +721,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) SilcChannelID *channel_id; unsigned char *tmp; SilcUInt32 len; + SilcBufferStruct buf; if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -734,9 +749,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) /* Get the invite list */ tmp = silc_argument_get_arg_type(cmd->args, 3, &len); - + if (tmp) + silc_buffer_set(&buf, tmp, len); + /* Notify application */ - COMMAND_REPLY((ARGS, channel, tmp)); + COMMAND_REPLY((SILC_ARGS, channel, tmp ? &buf : NULL)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INVITE); @@ -752,13 +769,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KILL); @@ -782,7 +799,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s", - silc_client_command_status_message(cmd->error)); + silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -818,7 +835,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) } /* Notify application */ - COMMAND_REPLY((ARGS, server, server->server_name, server->server_info)); + COMMAND_REPLY((SILC_ARGS, server, server->server_name, server->server_info)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO); @@ -826,6 +843,38 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) silc_client_command_reply_free(cmd); } +/* Received reply to STATS command. */ + +SILC_CLIENT_CMD_REPLY_FUNC(stats) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + unsigned char *tmp, *buf = NULL; + SilcUInt32 len, buf_len = 0; + + if (cmd->error != SILC_STATUS_OK) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_get_status_message(cmd->error)); + COMMAND_REPLY_ERROR; + goto out; + } + + /* Get server ID */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + if (!tmp) + goto out; + + /* Get statistics structure */ + buf = silc_argument_get_arg_type(cmd->args, 3, &buf_len); + + /* Notify application */ + COMMAND_REPLY((SILC_ARGS, buf, buf_len)); + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_STATS); + silc_client_command_reply_free(cmd); +} + /* Received reply to PING command. The reply time is shown to user. */ SILC_CLIENT_CMD_REPLY_FUNC(ping) @@ -838,7 +887,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -846,26 +895,26 @@ 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 || !conn->ping) { + if (!id || !conn->internal->ping) { COMMAND_REPLY_ERROR; goto out; } - for (i = 0; i < conn->ping_count; i++) { - if (!conn->ping[i].dest_id) + for (i = 0; i < conn->internal->ping_count; i++) { + if (!conn->internal->ping[i].dest_id) continue; - if (SILC_ID_SERVER_COMPARE(conn->ping[i].dest_id, id)) { - diff = curtime - conn->ping[i].start_time; + if (SILC_ID_SERVER_COMPARE(conn->internal->ping[i].dest_id, id)) { + diff = curtime - conn->internal->ping[i].start_time; SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Ping reply from %s: %d second%s", - conn->ping[i].dest_name, diff, + conn->internal->ping[i].dest_name, diff, diff == 1 ? "" : "s"); - conn->ping[i].start_time = 0; - silc_free(conn->ping[i].dest_id); - conn->ping[i].dest_id = NULL; - silc_free(conn->ping[i].dest_name); - conn->ping[i].dest_name = NULL; + conn->internal->ping[i].start_time = 0; + silc_free(conn->internal->ping[i].dest_id); + conn->internal->ping[i].dest_id = NULL; + silc_free(conn->internal->ping[i].dest_name); + conn->internal->ping[i].dest_name = NULL; break; } } @@ -873,7 +922,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping) silc_free(id); /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PING); @@ -899,13 +948,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) if (cmd->error != SILC_STATUS_OK) { if (cmd->error != SILC_STATUS_ERR_USER_ON_CHANNEL) SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } argc = silc_argument_get_arg_num(cmd->args); - if (argc < 7 || argc > 14) { + if (argc < 7) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "Cannot join channel: Bad reply packet"); COMMAND_REPLY_ERROR; @@ -1050,7 +1099,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) silc_client_save_channel_key(cmd->client, conn, keyp, channel); /* Notify application */ - COMMAND_REPLY((ARGS, channel_name, channel, mode, 0, + COMMAND_REPLY((SILC_ARGS, channel_name, channel, mode, 0, keyp ? keyp->head : NULL, NULL, NULL, topic, hmac, list_count, client_id_list, client_mode_list)); @@ -1078,7 +1127,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; return; } @@ -1101,7 +1150,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) while(cp[i] != 0) { if (cp[i++] == '\n') { memset(line, 0, sizeof(line)); - strncat(line, cp, i - 1); + silc_strncat(line, sizeof(line), cp, i - 1); cp += i; if (i == 2) @@ -1117,7 +1166,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) } /* Notify application */ - COMMAND_REPLY((ARGS, motd)); + COMMAND_REPLY((SILC_ARGS, motd)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_MOTD); @@ -1135,7 +1184,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -1150,7 +1199,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode) conn->local_entry->mode = mode; /* Notify application */ - COMMAND_REPLY((ARGS, mode)); + COMMAND_REPLY((SILC_ARGS, mode)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_UMODE); @@ -1171,7 +1220,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -1191,7 +1240,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) COMMAND_REPLY_ERROR; goto out; } - + /* Get channel mode */ tmp = silc_argument_get_arg_type(cmd->args, 3, NULL); if (!tmp) { @@ -1205,7 +1254,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) channel->mode = mode; /* Notify application */ - COMMAND_REPLY((ARGS, channel, mode)); + COMMAND_REPLY((SILC_ARGS, channel, mode)); silc_free(channel_id); @@ -1230,7 +1279,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -1288,7 +1337,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) chu->mode = mode; /* Notify application */ - COMMAND_REPLY((ARGS, mode, channel, client_entry)); + COMMAND_REPLY((SILC_ARGS, mode, channel, client_entry)); silc_free(client_id); silc_free(channel_id); @@ -1304,13 +1353,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(kick) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KICK); @@ -1324,13 +1373,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(silcoper) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SILCOPER); @@ -1344,13 +1393,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(oper) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_OPER); @@ -1365,13 +1414,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(detach) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); /* Generate the detachment data and deliver it to the client in the detach client operation */ @@ -1387,6 +1436,26 @@ SILC_CLIENT_CMD_REPLY_FUNC(detach) silc_client_command_reply_free(cmd); } +SILC_CLIENT_CMD_REPLY_FUNC(watch) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + + if (cmd->error != SILC_STATUS_OK) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_get_status_message(cmd->error)); + COMMAND_REPLY_ERROR; + goto out; + } + + /* Notify application */ + COMMAND_REPLY((SILC_ARGS)); + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WATCH); + silc_client_command_reply_free(cmd); +} + SILC_CLIENT_CMD_REPLY_FUNC(ban) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; @@ -1395,10 +1464,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban) SilcChannelID *channel_id; unsigned char *tmp; SilcUInt32 len; + SilcBufferStruct buf; if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -1422,9 +1492,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban) /* Get the ban list */ tmp = silc_argument_get_arg_type(cmd->args, 3, &len); - + if (tmp) + silc_buffer_set(&buf, tmp, len); + /* Notify application */ - COMMAND_REPLY((ARGS, channel, tmp)); + COMMAND_REPLY((SILC_ARGS, channel, tmp ? &buf : NULL)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN); @@ -1444,7 +1516,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -1468,7 +1540,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave) } /* Notify application */ - COMMAND_REPLY((ARGS, channel)); + COMMAND_REPLY((SILC_ARGS, channel)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LEAVE); @@ -1489,7 +1561,7 @@ static void silc_client_command_reply_users_cb(SilcClient client, cmd->status = cmd->error = SILC_STATUS_ERR_NO_SUCH_CHANNEL; SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS); silc_client_command_reply_free(cmd); @@ -1501,7 +1573,7 @@ static void silc_client_command_reply_users_cb(SilcClient client, static int silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, - SilcCommandStatus status, + SilcStatus status, bool notify, SilcGetChannelCallback get_channel, SilcCommandCb get_clients) @@ -1517,6 +1589,7 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, int i; unsigned char **res_argv = NULL; SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0; + bool wait_res = FALSE; SILC_LOG_DEBUG(("Start")); @@ -1566,6 +1639,8 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, return 1; } + SILC_LOG_DEBUG(("channel %s, %d users", channel->channel_name, list_count)); + /* Cache the received Client ID's and modes. */ for (i = 0; i < list_count; i++) { SilcUInt16 idp_len; @@ -1585,15 +1660,6 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, /* Check if we have this client cached already. */ 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. */ @@ -1605,7 +1671,7 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, (res_argc + 1)); res_argv[res_argc] = client_id_list.data; res_argv_lens[res_argc] = idp_len; - res_argv_types[res_argc] = res_argc + 3; + res_argv_types[res_argc] = res_argc + 4; res_argc++; } else { if (!silc_client_on_channel(channel, client_entry)) { @@ -1652,7 +1718,10 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, silc_free(res_argv_types); return 1; } - + + if (wait_res) + return 1; + silc_buffer_push(&client_id_list, (client_id_list.data - client_id_list.head)); silc_buffer_push(&client_mode_list, (client_mode_list.data - @@ -1660,7 +1729,7 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, /* Notify application */ if (notify) - COMMAND_REPLY((ARGS, channel, list_count, &client_id_list, + COMMAND_REPLY((SILC_ARGS, channel, list_count, &client_id_list, &client_mode_list)); out: @@ -1675,12 +1744,20 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcClientCommandReplyContext r = (SilcClientCommandReplyContext)context2; SILC_LOG_DEBUG(("Start")); if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); + COMMAND_REPLY_ERROR; + goto out; + } + + if (r && !silc_command_get_status(r->payload, NULL, &cmd->error)) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -1707,10 +1784,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) SilcClientEntry client_entry; SilcServerID *server_id = NULL; SilcServerEntry server_entry; - SilcSKEPKType type; - unsigned char *tmp, *pk; + unsigned char *tmp; SilcUInt32 len; - SilcUInt16 pk_len; SilcIdType id_type; SilcPublicKey public_key = NULL; @@ -1718,7 +1793,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } @@ -1737,15 +1812,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) /* Get the public key payload */ tmp = silc_argument_get_arg_type(cmd->args, 3, &len); if (tmp) { - /* Decode the public key */ - SILC_GET16_MSB(pk_len, tmp); - SILC_GET16_MSB(type, tmp + 2); - pk = tmp + 4; - - if (type == SILC_SKE_PK_TYPE_SILC) - if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key)) - public_key = NULL; - } + if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key)) + public_key = NULL; + } id_type = silc_id_payload_get_type(idp); if (id_type == SILC_ID_CLIENT) { @@ -1757,8 +1826,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) goto out; } + /* Save fingerprint */ + if (!client_entry->fingerprint) { + client_entry->fingerprint = silc_calloc(20, sizeof(unsigned char)); + client_entry->fingerprint_len = 20; + silc_hash_make(cmd->client->sha1hash, tmp + 4, len - 4, + client_entry->fingerprint); + } + /* Notify application */ - COMMAND_REPLY((ARGS, id_type, client_entry, public_key)); + COMMAND_REPLY((SILC_ARGS, id_type, client_entry, public_key)); } else if (id_type == SILC_ID_SERVER) { /* Received server's public key */ server_id = silc_id_payload_get_id(idp); @@ -1769,7 +1846,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) } /* Notify application */ - COMMAND_REPLY((ARGS, id_type, server_entry, public_key)); + COMMAND_REPLY((SILC_ARGS, id_type, server_entry, public_key)); } out: @@ -1800,10 +1877,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois_i) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; - SILC_LOG_DEBUG(("Start")); - - if (cmd->error != SILC_STATUS_OK) - goto out; + COMMAND_CHECK_STATUS_I; /* Save WHOIS info */ silc_client_command_reply_whois_save(cmd, cmd->status, FALSE); @@ -1818,6 +1892,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois_i) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS); + err: /* If we received notify for invalid ID we'll remove the ID if we have it cached. */ if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { @@ -1851,10 +1926,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify_i) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; - SILC_LOG_DEBUG(("Start")); - - if (cmd->error != SILC_STATUS_OK) - goto out; + COMMAND_CHECK_STATUS_I; /* Save IDENTIFY info */ silc_client_command_reply_identify_save(cmd, cmd->status, FALSE); @@ -1869,6 +1941,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify_i) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY); + err: /* If we received notify for invalid ID we'll remove the ID if we have it cached. */ if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { @@ -1907,10 +1980,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i) char *server_name, *server_info; SilcUInt32 len; - SILC_LOG_DEBUG(("Start")); - - if (cmd->error != SILC_STATUS_OK) - goto out; + COMMAND_CHECK_STATUS_I; /* Get server ID */ tmp = silc_argument_get_arg_type(cmd->args, 2, &len); @@ -1942,6 +2012,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO); silc_free(server_id); + err: silc_client_command_reply_free(cmd); } @@ -1957,7 +2028,7 @@ static void silc_client_command_reply_users_i_cb(SilcClient client, cmd->status = cmd->error = SILC_STATUS_ERR_NO_SUCH_CHANNEL; SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS); silc_client_command_reply_free(cmd); @@ -1971,10 +2042,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users_i) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; - SILC_LOG_DEBUG(("Start")); - - if (cmd->error != SILC_STATUS_OK) - goto out; + COMMAND_CHECK_STATUS_I; /* Save USERS info */ if (silc_client_command_reply_users_save( @@ -1986,6 +2054,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users_i) out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS); + err: /* Unregister this command reply */ silc_client_command_unregister(cmd->client, SILC_COMMAND_USERS, NULL, silc_client_command_reply_users_i, @@ -2004,13 +2073,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(connect) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_CONNECT); @@ -2024,13 +2093,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(close) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_CLOSE); @@ -2044,13 +2113,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown) if (cmd->error != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->error)); + "%s", silc_get_status_message(cmd->error)); COMMAND_REPLY_ERROR; goto out; } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((SILC_ARGS)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_SHUTDOWN);