#include "server_internal.h"
#include "command_reply.h"
+#define COMMAND_CHECK_STATUS \
+do { \
+ SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
+ if (status != SILC_STATUS_OK) { \
+ silc_server_command_reply_free(cmd); \
+ return; \
+ } \
+} while(0)
+
+#define COMMAND_CHECK_STATUS_LIST \
+do { \
+ 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) { \
+ silc_server_command_reply_free(cmd); \
+ return; \
+ } \
+} while(0)
+
/* Server command reply list. Not all commands have reply function as
they are never sent by server. More maybe added later if need appears. */
SilcServerCommandReply silc_command_reply_list[] =
{
SILC_SERVER_CMD_REPLY(join, JOIN),
+ SILC_SERVER_CMD_REPLY(identify, WHOIS),
SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
{ NULL, 0 },
SilcSocketConnection sock,
SilcBuffer buffer)
{
+ SilcServerCommandReply *cmd;
SilcServerCommandReplyContext ctx;
SilcCommandPayload payload;
+ SilcCommand command;
+ unsigned short ident;
/* Get command reply payload from packet */
payload = silc_command_payload_parse(buffer);
ctx->sock = sock;
ctx->payload = payload;
ctx->args = silc_command_get_args(ctx->payload);
+ ident = silc_command_get_ident(ctx->payload);
/* Check for pending commands and mark to be exeucted */
- SILC_SERVER_COMMAND_CHECK_PENDING(ctx);
-
+ silc_server_command_pending_check(ctx, silc_command_get(ctx->payload),
+ ident);
+
/* Execute command reply */
- SILC_SERVER_COMMAND_REPLY_EXEC(ctx);
+ command = silc_command_get(ctx->payload);
+ for (cmd = silc_command_reply_list; cmd->cb; cmd++)
+ if (cmd->cmd == command)
+ break;
+
+ if (cmd == NULL) {
+ silc_free(ctx);
+ return;
+ }
+
+ cmd->cb(ctx);
}
/* Free command reply context and its internals. */
}
}
-/* Received reply for forwarded JOIN command. Router has created or joined
- the client to the channel. We save some channel information locally
- for future use. */
+/* Caches the received WHOIS information. If we are normal server currently
+ we cache global information only for short period of time. If we are
+ router we want to cache them a bit longer since we can receive information
+ if any of the information becomes invalid. Normal server cannot receive
+ that information. Returns FALSE if something was wrong with the reply. */
-SILC_SERVER_CMD_REPLY_FUNC(join)
+static char
+silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
+{
+ int len, id_len;
+ unsigned char *id_data;
+ char *nickname, *username, *realname;
+ SilcClientID *client_id;
+
+ id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
+ nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
+ username = silc_argument_get_arg_type(cmd->args, 4, &len);
+ realname = silc_argument_get_arg_type(cmd->args, 5, &len);
+ if (!id_data || !nickname || !username || !realname)
+ return FALSE;
+
+ client_id = silc_id_payload_parse_id(id_data, id_len);
+
+
+ return TRUE;
+}
+
+/* Reiceved reply for WHOIS command. We sent the whois request to our
+ primary router, if we are normal server, and thus has now received reply
+ to the command. We will figure out what client originally sent us the
+ command and will send the reply to it. If we are router we will figure
+ out who server sent us the command and send reply to that one. */
+
+SILC_SERVER_CMD_REPLY_FUNC(whois)
{
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
SilcServer server = cmd->server;
SilcCommandStatus status;
- SilcChannelID *id;
- SilcChannelEntry entry;
- unsigned int len;
- unsigned char *id_string;
- char *channel_name, *tmp;
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;
+ COMMAND_CHECK_STATUS_LIST;
- /* Get channel name */
- tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
- if (!tmp)
- goto out;
+ /* Process one identify reply */
+ if (status == SILC_STATUS_OK) {
- /* Get channel ID */
- id_string = silc_argument_get_arg_type(cmd->args, 3, &len);
- if (!id_string)
- goto out;
+ }
- channel_name = strdup(tmp);
+ if (status == SILC_STATUS_LIST_START) {
- /* Add the channel to our local list. */
- id = silc_id_payload_parse_id(id_string, len);
- entry = silc_idlist_add_channel(server->local_list, channel_name,
- SILC_CHANNEL_MODE_NONE, id,
- server->id_entry->router, NULL);
- if (!entry) {
- silc_free(channel_name);
- silc_free(id);
- goto out;
}
- entry->global_users = TRUE;
+ if (status == SILC_STATUS_LIST_ITEM) {
- /* Execute pending JOIN command so that the client who originally
- wanted to join the channel will be joined after all. */
- SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
+ }
+
+ if (status == SILC_STATUS_LIST_END) {
+
+ }
+
+ /* Execute pending IDENTIFY command so that the client who originally
+ requested the identify information will get it after all. */
+ SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
out:
silc_server_command_reply_free(cmd);
SILC_LOG_DEBUG(("Start"));
- SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
- if (status != SILC_STATUS_OK)
- goto out;
+ COMMAND_CHECK_STATUS_LIST;
/* Process one identify reply */
if (status == SILC_STATUS_OK) {
}
+ if (status == SILC_STATUS_LIST_ITEM) {
+
+ }
+
if (status == SILC_STATUS_LIST_END) {
}
out:
silc_server_command_reply_free(cmd);
}
+
+/* Received reply for forwarded JOIN command. Router has created or joined
+ the client to the channel. We save some channel information locally
+ for future use. */
+
+SILC_SERVER_CMD_REPLY_FUNC(join)
+{
+ SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+ SilcServer server = cmd->server;
+ SilcCommandStatus status;
+ SilcChannelID *id;
+ SilcChannelEntry entry;
+ unsigned int len;
+ unsigned char *id_string;
+ char *channel_name, *tmp;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ COMMAND_CHECK_STATUS;
+
+ /* Get channel name */
+ tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+ if (!tmp)
+ goto out;
+
+ /* Get channel ID */
+ id_string = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (!id_string)
+ goto out;
+
+ channel_name = strdup(tmp);
+
+ /* Add the channel to our local list. */
+ id = silc_id_payload_parse_id(id_string, len);
+ entry = silc_idlist_add_channel(server->local_list, channel_name,
+ SILC_CHANNEL_MODE_NONE, id,
+ server->id_entry->router, NULL);
+ if (!entry) {
+ silc_free(channel_name);
+ silc_free(id);
+ goto out;
+ }
+
+ entry->global_users = TRUE;
+
+ /* Execute pending JOIN command so that the client who originally
+ wanted to join the channel will be joined after all. */
+ SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
+
+ out:
+ silc_server_command_reply_free(cmd);
+}