Watcher list support added.
[silc.git] / lib / silcclient / command_reply.c
index 415f6d49b2568d061250ac3eb84c88c1db7a0ddd..2e194d9ffdc2ee1d59ef23a4836e7e605f151686 100644 (file)
@@ -36,7 +36,7 @@
 #include "silcclient.h"
 #include "client_internal.h"
 
-const SilcCommandStatusMessage silc_command_status_messages[] = {
+const SilcStatusMessage silc_command_status_messages[] = {
 
   { STAT(NO_SUCH_NICK),      "There was no such nickname" },
   { STAT(NO_SUCH_CHANNEL),   "There was no such channel" },
@@ -127,9 +127,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 */
 
@@ -157,7 +158,7 @@ void silc_client_command_reply_process(SilcClient client,
 
 /* Returns status message string */
 
-char *silc_client_command_status_message(SilcCommandStatus status)
+char *silc_client_status_message(SilcStatus status)
 {
   int i;
 
@@ -184,7 +185,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;
@@ -267,7 +268,7 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
     client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING;
 
   /* Notify application */
-  if (!cmd->callback && notify)
+  if (!cmd->callbacks_count && notify)
     COMMAND_REPLY((ARGS, client_entry, nickname, username, realname, 
                   has_channels ? &channels : NULL, mode, idle, 
                   fingerprint, has_user_modes ? &ch_user_modes : NULL));
@@ -377,7 +378,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
 
 static void 
 silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
-                                       SilcCommandStatus status,
+                                       SilcStatus status,
                                        bool notify)
 {
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
@@ -553,7 +554,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -666,7 +667,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -720,7 +721,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
 
   if (cmd->error != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(cmd->error));
+       "%s", silc_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -762,7 +763,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -792,7 +793,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -848,7 +849,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -909,7 +910,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1088,7 +1089,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     return;
   }
@@ -1145,7 +1146,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1181,7 +1182,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1240,7 +1241,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1314,7 +1315,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1334,7 +1335,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1354,7 +1355,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1375,7 +1376,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1397,6 +1398,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_client_status_message(cmd->error));
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+
+  /* Notify application */
+  COMMAND_REPLY((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;
@@ -1408,7 +1429,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban)
 
   if (cmd->error != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(cmd->error));
+       "%s", silc_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1454,7 +1475,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1499,7 +1520,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
     silc_client_command_reply_free(cmd);
@@ -1511,7 +1532,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)
@@ -1527,6 +1548,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"));
 
@@ -1576,6 +1598,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;
@@ -1597,11 +1621,18 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd,
     if (!client_entry || !client_entry->username || !client_entry->realname) {
       if (client_entry) {
        if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
+         /* Attach to this resolving and wait until it finishes */
+         silc_client_command_pending(conn, SILC_COMMAND_NONE, 
+                                     client_entry->resolve_cmd_ident,
+                                     get_clients, cmd);
+         wait_res = TRUE;
+
          silc_buffer_pull(&client_id_list, idp_len);
          silc_buffer_pull(&client_mode_list, 4);
          continue;
        }
        client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
+       client_entry->resolve_cmd_ident = conn->cmd_ident + 1;
       }
 
       /* No we don't have it (or it is incomplete in information), query
@@ -1662,7 +1693,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 - 
@@ -1690,7 +1724,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
 
   if (cmd->error != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(cmd->error));
+       "%s", silc_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1728,7 +1762,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1967,7 +2001,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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
     silc_client_command_reply_free(cmd);
@@ -2014,7 +2048,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -2034,7 +2068,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -2054,7 +2088,7 @@ 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_client_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }