updates.
[silc.git] / lib / silcclient / command_reply.c
index 415f6d49b2568d061250ac3eb84c88c1db7a0ddd..43376be33248cbe3706aba68a4ac69f40e540061 100644 (file)
 #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 
@@ -127,9 +83,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,23 +112,6 @@ void silc_client_command_reply_process(SilcClient client,
   }
 }
 
-/* Returns status message string */
-
-char *silc_client_command_status_message(SilcCommandStatus status)
-{
-  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;
-}
-
 /* Free command reply context and its internals. */
 
 void silc_client_command_reply_free(SilcClientCommandReplyContext cmd)
@@ -184,7 +124,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 +207,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 +317,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 +493,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -666,7 +606,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;
   }
@@ -720,7 +660,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -762,7 +702,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -792,7 +732,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;
   }
@@ -848,7 +788,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;
   }
@@ -909,7 +849,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1088,7 +1028,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;
   }
@@ -1145,7 +1085,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;
   }
@@ -1181,7 +1121,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;
   }
@@ -1240,7 +1180,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;
   }
@@ -1314,7 +1254,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1334,7 +1274,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1354,7 +1294,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1375,7 +1315,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1397,6 +1337,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((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 +1368,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1454,7 +1414,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;
   }
@@ -1499,7 +1459,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);
@@ -1511,7 +1471,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 +1487,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 +1537,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 +1560,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 +1632,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 +1663,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1728,7 +1701,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;
   }
@@ -1967,7 +1940,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);
@@ -2014,7 +1987,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -2034,7 +2007,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -2054,7 +2027,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_get_status_message(cmd->error));
     COMMAND_REPLY_ERROR;
     goto out;
   }