Fixes to NAMES command handling.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 6 Jul 2000 07:14:36 +0000 (07:14 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 6 Jul 2000 07:14:36 +0000 (07:14 +0000)
Fixes when leaving from channel.

apps/silc/client.c
apps/silc/command.c
apps/silc/command_reply.c

index b64b6ac1a7c3b4ac07e256a0e4a434ba77a1438e..bc2a9fc3fa53b92b81241f3ff55230e16e683bae 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.5  2000/07/06 07:14:36  priikone
+ *     Fixes to NAMES command handling.
+ *     Fixes when leaving from channel.
+ *
  * Revision 1.4  2000/07/05 06:12:05  priikone
  *     Global cosmetic changes.
  *
@@ -2013,6 +2017,8 @@ void silc_client_close_connection(SilcClient client,
   if (sock->user_data) {
     win = (SilcClientWindow)sock->user_data;
 
+    /* XXX Free all client entries and channel entries. */
+
     /* Clear ID caches */
     for (i = 0; i < 96; i++)
       silc_idcache_del_all(&win->client_id_cache[i], 
@@ -2050,6 +2056,7 @@ void silc_client_close_connection(SilcClient client,
     win->local_id = NULL;
     win->local_id_data = NULL;
     win->remote_host = NULL;
+    win->current_channel = NULL;
   }
 
   if (sock->protocol) {
index dad802e0af040ccb454f767129d9b14d56e6218a..7b6e8c17e5c9a769ca6e361a0847668e9d076115 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.6  2000/07/06 07:14:36  priikone
+ *     Fixes to NAMES command handling.
+ *     Fixes when leaving from channel.
+ *
  * Revision 1.5  2000/07/05 06:12:05  priikone
  *     Global cosmetic changes.
  *
@@ -310,7 +314,7 @@ SILC_CLIENT_CMD_FUNC(server)
     port = atoi(cmd->argv[1] + 1 + len);
   } else {
     hostname = cmd->argv[1];
-    port = 334;
+    port = 706;
   }
 
   /* Connect asynchronously to not to block user interface */
@@ -389,8 +393,8 @@ SILC_CLIENT_CMD_FUNC(invite)
   channel_id = silc_id_id2str(id_cache->id, SILC_ID_CHANNEL);
 
   buffer = silc_command_encode_payload_va(SILC_COMMAND_INVITE, 2,
-                                         client_id, SILC_ID_CLIENT_LEN,
-                                         channel_id, SILC_ID_CHANNEL_LEN);
+                                         1, client_id, SILC_ID_CLIENT_LEN,
+                                         2, channel_id, SILC_ID_CHANNEL_LEN);
   silc_client_packet_send(cmd->client, cmd->sock,
                          SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
                          buffer->data, buffer->len, TRUE);
@@ -475,7 +479,7 @@ SILC_CLIENT_CMD_FUNC(ping)
 
   /* Send the command */
   buffer = silc_command_encode_payload_va(SILC_COMMAND_PING, 1, 
-                                         win->remote_id_data, 
+                                         1, win->remote_id_data, 
                                          SILC_ID_SERVER_LEN);
   silc_client_packet_send(cmd->client, cmd->client->current_win->sock,
                          SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
@@ -636,27 +640,32 @@ SILC_CLIENT_CMD_FUNC(leave)
 
   win = (SilcClientWindow)cmd->sock->user_data;
 
-  if (cmd->argv[1][0] == '*')
+  if (cmd->argv[1][0] == '*') {
+    if (!win->current_channel) {
+      silc_say(cmd->client, "You are not on any chanenl");
+      goto out;
+    }
     name = win->current_channel->channel_name;
-  else
+  } else {
     name = cmd->argv[1];
+  }
 
   if (!win->current_channel) {
-    silc_say(cmd->client, "You are not on that channel", name);
+    silc_say(cmd->client, "You are not on that channel");
     goto out;
   }
 
   /* Get the Channel ID of the channel */
   silc_idcache_find_by_data(CIDC(name[0]), CIDCC(name[0]), name, &id_cache);
   if (!id_cache) {
-    silc_say(cmd->client, "You are not on that channel", name);
+    silc_say(cmd->client, "You are not on that channel");
     goto out;
   }
 
   /* Send LEAVE command to the server */
   id_string = silc_id_id2str(id_cache->id, SILC_ID_CHANNEL);
   buffer = silc_command_encode_payload_va(SILC_COMMAND_LEAVE, 1, 
-                                         id_string, SILC_ID_CHANNEL_LEN);
+                                         1, id_string, SILC_ID_CHANNEL_LEN);
   silc_client_packet_send(cmd->client, cmd->client->current_win->sock,
                          SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
                          buffer->data, buffer->len, TRUE);
@@ -726,13 +735,24 @@ SILC_CLIENT_CMD_FUNC(names)
   /* Send NAMES command to the server */
   id_string = silc_id_id2str(id_cache->id, SILC_ID_CHANNEL);
   buffer = silc_command_encode_payload_va(SILC_COMMAND_NAMES, 1, 
-                                         id_string, SILC_ID_CHANNEL_LEN);
+                                         1, id_string, SILC_ID_CHANNEL_LEN);
   silc_client_packet_send(cmd->client, cmd->client->current_win->sock,
                          SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
                          buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
   silc_free(id_string);
 
+  /* Register dummy pending command that will tell the reply command
+     that user called this command. Server may send reply to this command
+     even if user did not send this command thus we want to handle things
+     differently when user sent the command. This is dummy and won't be
+     execute. */
+  /* XXX this is kludge and should be removed after pending command reply 
+     support is added. Currently only commands may be pending not command
+     replies. */
+  silc_client_command_pending(SILC_COMMAND_NAMES, silc_client_command_names,
+                             NULL);
+
  out:
   silc_client_command_free(cmd);
 #undef CIDC
index 776b9b9de2ec4e9a677b0a8ece06ef35bba0c3c0..fde7a173582258ac182c908c0543ab34e96ff92c 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.5  2000/07/06 07:14:36  priikone
+ *     Fixes to NAMES command handling.
+ *     Fixes when leaving from channel.
+ *
  * Revision 1.4  2000/07/05 06:12:34  priikone
  *     Tweaked NAMES command reply for better. Should now show users
  *     joined to a channel.
@@ -201,9 +205,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
   SILC_GET16_MSB(status, tmp);
   if (status != SILC_STATUS_OK) {
     if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
-      tmp += 2;
-      silc_say(cmd->client, "%s: %s", tmp,
-              silc_client_command_status_message(status));
+      /* Take nickname which may be provided */
+      tmp = silc_command_get_arg_type(cmd->payload, 3, NULL);
+      if (tmp)
+       silc_say(cmd->client, "%s: %s", tmp,
+                silc_client_command_status_message(status));
+      else
+       silc_say(cmd->client, "%s",
+                silc_client_command_status_message(status));
       goto out;
     } else {
       silc_say(cmd->client, "%s", silc_client_command_status_message(status));
@@ -297,9 +306,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
   SILC_GET16_MSB(status, tmp);
   if (status != SILC_STATUS_OK) {
     if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
-      tmp += 2;
-      silc_say(cmd->client, "%s: %s", tmp,
-              silc_client_command_status_message(status));
+      /* Take nickname which may be provided */
+      tmp = silc_command_get_arg_type(cmd->payload, 3, NULL);
+      if (tmp)
+       silc_say(cmd->client, "%s: %s", tmp,
+                silc_client_command_status_message(status));
+      else
+       silc_say(cmd->client, "%s",
+                silc_client_command_status_message(status));
       goto out;
     } else {
       silc_say(cmd->client, "%s", silc_client_command_status_message(status));
@@ -502,14 +516,25 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
 
   /* Get channel name */
   tmp = silc_command_get_arg_type(cmd->payload, 2, NULL);
+  if (!tmp) {
+    silc_say(cmd->client, "Cannot join channel: Bad reply packet");
+    goto out;
+  }
   channel_name = strdup(tmp);
 
   /* Get Channel ID */
   id_string = silc_command_get_arg_type(cmd->payload, 3, NULL);
+  if (!id_string) {
+    silc_say(cmd->client, "Cannot join channel: Bad reply packet");
+    goto out;
+  }
 
   /* Get channel mode */
   tmp = silc_command_get_arg_type(cmd->payload, 4, NULL);
-  SILC_GET32_MSB(mode, tmp);
+  if (tmp)
+    SILC_GET32_MSB(mode, tmp);
+  else
+    mode = 0;
 
   /* Get topic */
   topic = silc_command_get_arg_type(cmd->payload, 5, NULL);
@@ -589,14 +614,17 @@ SILC_CLIENT_CMD_REPLY_FUNC(names)
   SilcIDCache *id_cache = NULL;
   SilcChannelEntry channel;
   SilcChannelID *channel_id = NULL;
+  SilcBuffer client_id_list;
   unsigned char *tmp;
   char *name_list;
-  int i, len;
+  int i, len1, len2, list_count = 0;
 
   SILC_LOG_DEBUG(("Start"));
 
 #define CIDC(x) win->channel_id_cache[(x)]
 #define CIDCC(x) win->channel_id_cache_count[(x)]
+#define CLC(x) win->client_id_cache[(x) - 32]
+#define CLCC(x) win->client_id_cache_count[(x) - 32]
 
   tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
   SILC_GET16_MSB(status, tmp);
@@ -607,14 +635,29 @@ SILC_CLIENT_CMD_REPLY_FUNC(names)
 
   /* Get channel ID */
   tmp = silc_command_get_arg_type(cmd->payload, 2, NULL);
-  if (!tmp)
+  if (!tmp) {
+    silc_say(cmd->client, "Cannot get user list: Bad reply packet");
     goto out;
+  }
   channel_id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
 
   /* Get the name list of the channel */
-  name_list = silc_command_get_arg_type(cmd->payload, 3, &len);
-  if (!name_list)
+  name_list = silc_command_get_arg_type(cmd->payload, 3, &len1);
+  if (!name_list) {
+    silc_say(cmd->client, "Cannot get user list: Bad reply packet");
+    goto out;
+  }
+
+  /* Get Client ID list */
+  tmp = silc_command_get_arg_type(cmd->payload, 4, &len2);
+  if (!tmp) {
+    silc_say(cmd->client, "Cannot get user list: Bad reply packet");
     goto out;
+  }
+
+  client_id_list = silc_buffer_alloc(len2);
+  silc_buffer_pull_tail(client_id_list, len2);
+  silc_buffer_put(client_id_list, tmp, len2);
 
   /* Get the channel name */
   for (i = 0; i < 96; i++) {
@@ -629,10 +672,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(names)
   
   channel = (SilcChannelEntry)id_cache->context;
 
-  /* If there are pending commands set for this command reply we will
-     execute them and let them handle the received name list. */
+  /* If there is pending command we know that user has called this command
+     and we will handle the name list differently. */
   if (cmd->callback) {
-    SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_WHOIS);
+    /* We will resolve all the necessary information about the people
+       on the channel. Only after that will we display the user list. */
+    for (i = 0; i < len1; i++) {
+      /* XXX */
+
+    }
+    silc_client_command_pending_del(SILC_COMMAND_NAMES);
   } else {
     /* there is no pending callback it means that this command reply
        has been received without calling the command, ie. server has sent
@@ -640,19 +689,49 @@ SILC_CLIENT_CMD_REPLY_FUNC(names)
        with SILC servers that sends NAMES reply after joining to a channel. */
 
     /* Remove commas from list */
-    for (i = 0; i < len; i++)
-      if (name_list[i] == ',')
+    for (i = 0; i < len1; i++)
+      if (name_list[i] == ',') {
        name_list[i] = ' ';
+       list_count++;
+      }
 
     silc_say(cmd->client, "Users on %s: %s", channel->channel_name, name_list);
   }
 
+  /* Cache the received name list and client ID's. This cache expires
+     whenever server sends notify message to channel. It means to things;
+     some user has joined or leaved the channel. */
+  for (i = 0; i < list_count; i++) {
+    int nick_len = strcspn(name_list, " ");
+    char *nickname = silc_calloc(nick_len, sizeof(*nickname));
+    SilcClientID *client_id;
+    SilcClientEntry client;
+
+    memcpy(nickname, name_list, nick_len);
+    client_id = silc_id_str2id(client_id_list->data, SILC_ID_CLIENT_LEN);
+    silc_buffer_pull(client_id_list, SILC_ID_CLIENT_LEN);
+
+    client = silc_calloc(1, sizeof(*client));
+    client->id = client_id;
+    client->nickname = nickname;
+
+    CLCC(nickname[0]) = silc_idcache_add(&CLC(nickname[0]), CLCC(nickname[0]),
+                                        nickname, SILC_ID_CLIENT, 
+                                        client_id, (void *)client);
+
+    name_list = name_list + nick_len + 1;
+  }
+
+  silc_buffer_free(client_id_list);
+
  out:
   if (channel_id)
     silc_free(channel_id);
   silc_client_command_reply_free(cmd);
 #undef CIDC
 #undef CIDCC
+#undef CLC
+#undef CLCC
 }
 
 /* Private message received. This processes the private message and