updates.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 30 Jan 2001 21:40:21 +0000 (21:40 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 30 Jan 2001 21:40:21 +0000 (21:40 +0000)
13 files changed:
CHANGES
apps/silc/local_command.c
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/server.c
lib/silcclient/client.c
lib/silcclient/client.h
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/command_reply.h
lib/silccore/silcpacket.h

diff --git a/CHANGES b/CHANGES
index 076bb2584d47a4bd2457d81b6f08f27a8dedc368..b147d9083cb69c22f26e26951eff682b55ce8fe5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,47 @@
+Tue Jan 30 22:39:15 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Changed the client's pending command handling to the same as the
+         server's pending command handling.  It is also now possible to
+         execute command reply functions from other command reply
+         function as the function callbacks for commands and command
+         replies are one and same.  The pending commands are not static
+         list anymore, it is mallocated SilcDList in lib/silcclient/client.h
+         in client connection context.  Thus, pending commands are server
+         connection specific as it is convenient.
+
+         Changed the function silc_client_command_pending and
+         silc_client_command_pending_del and added new function
+         silc_client_command_pending_check.  Removed the 
+         SILC_CLIENT_CMD_REPLY_EXEC, and SILC_CLIENT_PENDING_COMMAND_CHECK
+         macros.
+
+       * Added cmd_ident, current command identifier, to the client
+         connection context in lib/silcclient/client.h to keep track on
+         command identifiers used in command sending.  Client's command reply
+         function handling now supports the mandatory command identifiers.
+
+       * Added SILC_CLIENT_COMMAND_EXEC_PENDING macros to all command reply
+         funtions in client to fully support pending command callbacks.
+
+       * NOTE: the name_list in USERS (old NAMES) command is NOT sent anymore
+         as one of the arguments to the application in the command reply
+         client operation.
+
+       * NOTE: The FORWARDED flag is depracated.  It used to be depracated
+         before first releasing SILC but came back.  Now it is removed again
+         and should come back nomore.  The FORWARDED flag was used only
+         by the JOINing procedure by forwarding the command packet to router.
+         Now, the JOINing procedure has been changed to more generic (due
+         to various router environment issues) and FORWARDED is not needed
+         anymore for anything.  The protocol specification is yet to be
+         updated.
+
+         Now, removed silc_server_packet_forward from server and the flag
+         SILC_PACKET_FORWARDED from lib/silccore/silcpacket.h.
+
 Tue Jan 30 00:05:05 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-       * Renames NAMES command to USERS command.  The NAMES was named that
+       * Renamed NAMES command to USERS command.  The NAMES was named that
          due to historical reasons.  Now it is renamed.  Also, rewrote
          parts of the USERS command.  The nickname list is not sent anymore
          by the server.  Only Client ID and mode lists are sent in the USERS
@@ -14,7 +55,7 @@ Tue Jan 30 00:05:05 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
          in the network by sending only one WHOIS or IDENTIFY command.
          Changed the code and the protocol specifications.
 
-       * Remove silc_server_command_identify_parse and changed that IDENTIFY
+       * Removed silc_server_command_identify_parse and changed that IDENTIFY
          uses silc_server_command_whois_parse to parse the request. */
 
        * If normal server, do not parse the WHOIS and IDENTIFY requests
index 3d969f78165ac1aeb560a88fe7d3dc06b0fa69f8..110a8eb81092fa17fecc154d30a86f755a89aa3c 100644 (file)
@@ -20,6 +20,9 @@
 /*
  * $Id$
  * $Log$
+ * Revision 1.2  2001/01/30 21:40:21  priikone
+ *     updates.
+ *
  * Revision 1.1  2000/09/13 17:47:54  priikone
  *     Created SILC Client Libary by moving stuff from silc/ directory.
  *     SILC client library is SILC client without UI. Old UI still exists
@@ -137,7 +140,7 @@ SILC_CLIENT_LCMD_FUNC(msg)
   if (!client_entry) {
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
-    silc_client_command_pending(SILC_COMMAND_IDENTIFY, 
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0,
                                silc_client_local_command_msg, context);
     return;
   }
index 16513946bdfaf336741626d480b272fe27fd8566..57bdc9e867d38d0cbc69604056a2e21b34ae0096 100644 (file)
@@ -559,12 +559,12 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
 {
   SilcBuffer buffer = packet->buffer;
   SilcIDList id_list;
-  SilcServerEntry tmpserver, router;
+  SilcServerEntry router;
   SilcSocketConnection router_sock;
   SilcIDPayload idp;
   SilcIdType id_type;
   unsigned char *hash = NULL;
-  void *id, *tmpid;
+  void *id;
 
   SILC_LOG_DEBUG(("Processing new ID"));
 
index bbae2c24bf038fad4d2897c42d2532fd978d9cf4..70911cf0a4db4ba0d2943f3f20c9741be830d49d 100644 (file)
@@ -180,52 +180,6 @@ void silc_server_packet_send_dest(SilcServer server,
     silc_free(packetdata.dst_id);
 }
 
-/* Forwards packet. Packets sent with this function will be marked as
-   forwarded (in the SILC header flags) so that the receiver knows that
-   we have forwarded the packet to it. Forwarded packets are handled
-   specially by the receiver as they are not destined to the receiver
-   originally. However, the receiver knows this because the forwarded
-   flag has been set (and the flag is authenticated). */
-
-void silc_server_packet_forward(SilcServer server,
-                               SilcSocketConnection sock,
-                               unsigned char *data, unsigned int data_len,
-                               int force_send)
-{
-  SilcIDListData idata;
-  SilcCipher cipher = NULL;
-  SilcHmac hmac = NULL;
-
-  SILC_LOG_DEBUG(("Forwarding packet"));
-
-  /* Get data used in the packet sending, keys and stuff */
-  idata = (SilcIDListData)sock->user_data;
-
-  /* Prepare outgoing data buffer for packet sending */
-  silc_packet_send_prepare(sock, 0, 0, data_len);
-
-  /* Put the data to the buffer */
-  if (data && data_len)
-    silc_buffer_put(sock->outbuf, data, data_len);
-
-  /* Add the FORWARDED flag to packet flags */
-  sock->outbuf->data[2] |= (unsigned char)SILC_PACKET_FLAG_FORWARDED;
-
-  if (idata) {
-    cipher = idata->send_key;
-    hmac = idata->hmac;
-  }
-
-  /* Encrypt the packet */
-  silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
-
-  SILC_LOG_HEXDUMP(("Forwarded packet, len %d", sock->outbuf->len),
-                  sock->outbuf->data, sock->outbuf->len);
-
-  /* Now actually send the packet */
-  silc_server_packet_send_real(server, sock, force_send);
-}
-
 /* Broadcast received packet to our primary route. This function is used
    by router to further route received broadcast packet. It is expected
    that the broadcast flag from the packet is checked before calling this
index c4d71e1f041a09fbbf7029d003183eaaabbdf93b..c60bace93980e88f4603cf31480ff35decc58408 100644 (file)
@@ -42,10 +42,6 @@ void silc_server_packet_send_dest(SilcServer server,
                                  unsigned char *data, 
                                  unsigned int data_len,
                                  int force_send);
-void silc_server_packet_forward(SilcServer server,
-                               SilcSocketConnection sock,
-                               unsigned char *data, unsigned int data_len,
-                               int force_send);
 void silc_server_packet_broadcast(SilcServer server,
                                  SilcSocketConnection sock,
                                  SilcPacketContext *packet);
index 21b865e26e60545381ea1b3a33fd143a7673045c..c562e8685663d558d3b0b4eb7fdea49fc3435e99 100644 (file)
@@ -71,7 +71,9 @@ int silc_server_alloc(SilcServer *new_server)
 void silc_server_free(SilcServer server)
 {
   if (server) {
+#ifdef SILC_SIM
     SilcSimContext *sim;
+#endif
 
     if (server->local_list)
       silc_free(server->local_list);
@@ -1164,8 +1166,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   if (server->server_type == SILC_ROUTER) {
     /* Route the packet if it is not destined to us. Other ID types but
        server are handled separately after processing them. */
-    if (packet->dst_id_type == SILC_ID_SERVER &&
-       !(packet->flags & SILC_PACKET_FLAG_FORWARDED) && 
+    if (packet->dst_id_type == SILC_ID_SERVER && 
        sock->type != SILC_SOCKET_TYPE_CLIENT &&
        SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
       
@@ -1327,7 +1328,7 @@ void silc_server_packet_parse_type(SilcServer server,
     /*
      * Received command reply packet. Received command reply to command. It
      * may be reply to command sent by us or reply to command sent by client
-     * that we've forwarded.
+     * that we've routed further.
      */
     SILC_LOG_DEBUG(("Command Reply packet"));
     silc_server_command_reply(server, sock, packet);
index eaf4db454aad1a40604ea88f23dc66b6f3dd545b..8403f44a30f8dabef3c9e37b1707f633a008bfdc 100644 (file)
@@ -141,6 +141,7 @@ SilcClientConnection silc_client_add_connection(SilcClient client,
   conn->remote_host = strdup(hostname);
   conn->remote_port = port;
   conn->context = context;
+  conn->pending_commands = silc_dlist_init();
 
   /* Add the connection to connections table */
   for (i = 0; i < client->conns_count; i++)
@@ -165,6 +166,8 @@ void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
 
   for (i = 0; i < client->conns_count; i++)
     if (client->conns[i] == conn) {
+      if (conn->pending_commands)
+       silc_dlist_uninit(conn->pending_commands);
       silc_free(conn);
       client->conns[i] = NULL;
     }
@@ -1195,6 +1198,8 @@ void silc_client_close_connection(SilcClient client,
       memset(conn->hmac_key, 0, conn->hmac_key_len);
       silc_free(conn->hmac_key);
     }
+    if (conn->pending_commands)
+      silc_dlist_uninit(conn->pending_commands);
 
     conn->sock = NULL;
     conn->remote_port = 0;
@@ -1208,6 +1213,7 @@ void silc_client_close_connection(SilcClient client,
     conn->local_id_data = NULL;
     conn->remote_host = NULL;
     conn->current_channel = NULL;
+    conn->pending_commands = NULL;
 
     silc_client_del_connection(client, conn);
   }
@@ -1277,7 +1283,6 @@ void silc_client_notify_by_server(SilcClient client,
   SilcNotifyPayload payload;
   SilcNotifyType type;
   SilcArgumentPayload args;
-  int i;
 
   SilcClientID *client_id = NULL;
   SilcChannelID *channel_id = NULL;
@@ -1321,7 +1326,7 @@ void silc_client_notify_by_server(SilcClient client,
       SilcPacketContext *p = silc_packet_context_dup(packet);
       p->context = (void *)client;
       p->sock = sock;
-      silc_client_command_pending(SILC_COMMAND_WHOIS
+      silc_client_command_pending(conn,SILC_COMMAND_WHOIS, 0
                                  silc_client_notify_by_server_pending, p);
       goto out;
     }
@@ -1367,7 +1372,7 @@ void silc_client_notify_by_server(SilcClient client,
       SilcPacketContext *p = silc_packet_context_dup(packet);
       p->context = (void *)client;
       p->sock = sock;
-      silc_client_command_pending(SILC_COMMAND_WHOIS
+      silc_client_command_pending(conn, SILC_COMMAND_WHOIS, 0
                                  silc_client_notify_by_server_pending, p);
       goto out;
     }
@@ -1541,7 +1546,7 @@ void silc_client_notify_by_server(SilcClient client,
       SilcPacketContext *p = silc_packet_context_dup(packet);
       p->context = (void *)client;
       p->sock = sock;
-      silc_client_command_pending(SILC_COMMAND_WHOIS
+      silc_client_command_pending(conn, SILC_COMMAND_WHOIS, 0
                                  silc_client_notify_by_server_pending, p);
       goto out;
     }
@@ -1872,7 +1877,6 @@ void silc_client_channel_message(SilcClient client,
   SilcChannelUser chu;
   SilcIDCacheEntry id_cache = NULL;
   SilcClientID *client_id = NULL;
-  int i;
   char *nickname;
 
   /* Sanity checks */
@@ -2011,7 +2015,6 @@ void silc_client_remove_from_channels(SilcClient client,
   SilcIDCacheList list;
   SilcChannelEntry channel;
   SilcChannelUser chu;
-  int i;
 
   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
                               SILC_ID_CHANNEL, &list))
@@ -2055,7 +2058,6 @@ void silc_client_replace_from_channels(SilcClient client,
   SilcIDCacheList list;
   SilcChannelEntry channel;
   SilcChannelUser chu;
-  int i;
 
   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
                               SILC_ID_CHANNEL, &list))
index f6d2215af736de0a5ed75e41304d172fb653c164..0cf57a4964d0ae46e8a4f9d2fcdd3952c43b76eb 100644 (file)
@@ -110,6 +110,12 @@ struct SilcClientConnectionObject {
      referencing (sock->user_data). */
   SilcSocketConnection sock;
 
+  /* Pending command queue for this connection */
+  SilcDList pending_commands;
+
+  /* Current command identifier, 0 not used */
+  unsigned short cmd_ident;
+
   /* Requested pings. */
   SilcClientPing *ping;
   unsigned int ping_count;
index 2dc94102d549572c3871fb06a17439c8f678f24f..c543ed904100058a3d20008c59310ced3979a0b8 100644 (file)
@@ -74,9 +74,6 @@ SilcClientCommand silc_command_list[] =
 #define COMMAND_ERROR cmd->client->ops->command(cmd->client, cmd->conn, \
   cmd, FALSE, cmd->command->cmd)
 
-/* List of pending commands. */
-SilcClientCommandPending *silc_command_pending = NULL;
-
 /* Generic function to send any command. The arguments must be sent already
    encoded into correct form in correct order. */
 
@@ -110,63 +107,66 @@ SilcClientCommand *silc_client_command_find(const char *name)
   return NULL;
 }
 
-/* Add new pending command to the list of pending commands. Currently
-   pending commands are executed from command replies, thus we can
-   execute any command after receiving some specific command reply.
-
-   The argument `reply_cmd' is the command reply from where the callback
-   function is to be called, thus, it IS NOT the command to be executed.
+/* Add new pending command to be executed when reply to a command has been
+   received.  The `reply_cmd' is the command that will call the `callback'
+   with `context' when reply has been received.  If `ident is non-zero
+   the `callback' will be executed when received reply with command 
+   identifier `ident'. */
 
-   XXX: If needed in the future this support may be extended for
-   commands as well, when any command could be executed after executing
-   some specific command. */
-
-void silc_client_command_pending(SilcCommand reply_cmd,
-                                SilcClientCommandCallback callback,
+void silc_client_command_pending(SilcClientConnection conn,
+                                SilcCommand reply_cmd,
+                                unsigned short ident,
+                                SilcCommandCb callback,
                                 void *context)
 {
-  SilcClientCommandPending *reply, *r;
+  SilcClientCommandPending *reply;
 
   reply = silc_calloc(1, sizeof(*reply));
   reply->reply_cmd = reply_cmd;
+  reply->ident = ident;
   reply->context = context;
   reply->callback = callback;
+  silc_dlist_add(conn->pending_commands, reply);
+}
 
-  if (silc_command_pending == NULL) {
-    silc_command_pending = reply;
-    return;
-  }
+/* Deletes pending command by reply command type. */
 
-  for (r = silc_command_pending; r; r = r->next) {
-    if (r->next == NULL) {
-      r->next = reply;
+void silc_client_command_pending_del(SilcClientConnection conn,
+                                    SilcCommand reply_cmd,
+                                    unsigned short ident)
+{
+  SilcClientCommandPending *r;
+
+  silc_dlist_start(conn->pending_commands);
+  while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) {
+    if (r->reply_cmd == reply_cmd && r->ident == ident) {
+      silc_dlist_del(conn->pending_commands, r);
       break;
     }
   }
 }
 
-/* Deletes pending command by reply command type. */
+/* Checks for pending commands and marks callbacks to be called from
+   the command reply function. Returns TRUE if there were pending command. */
 
-void silc_client_command_pending_del(SilcCommand reply_cmd)
+int silc_client_command_pending_check(SilcClientConnection conn,
+                                     SilcClientCommandReplyContext ctx,
+                                     SilcCommand command, 
+                                     unsigned short ident)
 {
-  SilcClientCommandPending *r, *tmp;
-  
-  if (silc_command_pending) {
-    if (silc_command_pending->reply_cmd == reply_cmd) {
-      silc_free(silc_command_pending);
-      silc_command_pending = NULL;
-      return;
-    }
-
-    for (r = silc_command_pending; r; r = r->next) {
-      if (r->next && r->next->reply_cmd == reply_cmd) {
-       tmp = r->next;
-       r->next = r->next->next;
-       silc_free(tmp);
-       break;
-      }
+  SilcClientCommandPending *r;
+
+  silc_dlist_start(conn->pending_commands);
+  while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) {
+    if (r->reply_cmd == command && r->ident == ident) {
+      ctx->context = r->context;
+      ctx->callback = r->callback;
+      ctx->ident = ident;
+      return TRUE;
     }
   }
+
+  return FALSE;
 }
 
 /* Free command context and its internals */
@@ -445,7 +445,7 @@ SILC_CLIENT_CMD_FUNC(invite)
 
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
-    silc_client_command_pending(SILC_COMMAND_IDENTIFY, 
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0,
                                silc_client_command_invite, context);
     return;
   }
@@ -988,7 +988,7 @@ SILC_CLIENT_CMD_FUNC(cumode)
   if (!client_entry) {
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
-    silc_client_command_pending(SILC_COMMAND_CUMODE, 
+    silc_client_command_pending(conn, SILC_COMMAND_CUMODE, 0,  
                                silc_client_command_cumode, context);
     return;
   }
@@ -1230,7 +1230,7 @@ SILC_CLIENT_CMD_FUNC(users)
   /* 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_USERS
+  silc_client_command_pending(conn, SILC_COMMAND_USERS, 0
                              silc_client_command_users, NULL);
 
   /* Notify application */
index 7e7db0e9a32b2b8ef90dc8e7078fffbde90ccf7d..dfe4f586d4d19349b8bfae98cc576791bbb727f3 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef COMMAND_H
 #define COMMAND_H
 
+#include "command_reply.h"
+
 /* 
    Structure holding one command and pointer to its function. 
 
@@ -59,10 +61,6 @@ typedef struct {
 /* All client commands */
 extern SilcClientCommand silc_command_list[];
 
-/* Client command callback function. This included into Command Context, 
-   and if it is defined it will be executed when executing the command. */
-typedef void (*SilcClientCommandCallback)(void *context);
-
 /* Context sent as argument to all commands */
 typedef struct {
   SilcClient client;
@@ -80,9 +78,9 @@ typedef struct {
    replies, if needed later. */
 typedef struct SilcClientCommandPendingStruct {
   SilcCommand reply_cmd;
+  SilcCommandCb callback;
   void *context;
-  SilcClientCommandCallback callback;
-
+  unsigned short ident;
   struct SilcClientCommandPendingStruct *next;
 } SilcClientCommandPending;
 
@@ -99,31 +97,14 @@ extern SilcClientCommandPending *silc_command_pending;
 #define SILC_CLIENT_CMD_FUNC(func) \
 void silc_client_command_##func(void *context)
 
-/* Checks for pending commands */
-#define SILC_CLIENT_COMMAND_CHECK_PENDING(ctx)         \
-do {                                                   \
-  if (silc_command_pending) {                          \
-    SilcClientCommandPending *r;                       \
-    SilcCommand cmd;                                   \
-                                                       \
-    cmd = silc_command_get(payload);                   \
-    for (r = silc_command_pending; r; r = r->next) {   \
-      if (r->reply_cmd == cmd) {                       \
-       ctx->context = r->context;                      \
-       ctx->callback = r->callback;                    \
-       break;                                          \
-      }                                                        \
-    }                                                  \
-  }                                                    \
-} while(0)
-
-/* Executed pending command */
-#define SILC_CLIENT_COMMAND_EXEC_PENDING(ctx, cmd)     \
-do {                                                   \
-  if (ctx->callback) {                                 \
-    (*ctx->callback)(ctx->context);                    \
-    silc_client_command_pending_del((cmd));            \
-  }                                                    \
+/* Executed pending command callback */
+#define SILC_CLIENT_COMMAND_EXEC_PENDING(ctx, cmd)                     \
+do {                                                                   \
+  if ((ctx)->callback) {                                               \
+    (*ctx->callback)(ctx->context);                                    \
+    silc_client_command_pending_del((ctx)->sock->user_data, (cmd),     \
+                                   (ctx)->ident);                      \
+  }                                                                    \
 } while(0)
 
 /* Prototypes */
@@ -131,10 +112,18 @@ void silc_client_command_free(SilcClientCommandContext cmd);
 void silc_client_send_command(SilcClient client, SilcClientConnection conn,
                              SilcCommand command, unsigned int argc, ...);
 SilcClientCommand *silc_client_command_find(const char *name);
-void silc_client_command_pending(SilcCommand reply_cmd,
-                                SilcClientCommandCallback callback,
+void silc_client_command_pending(SilcClientConnection conn,
+                                SilcCommand reply_cmd,
+                                unsigned short ident,
+                                SilcCommandCb callback,
                                 void *context);
-void silc_client_command_pending_del(SilcCommand reply_cmd);
+void silc_client_command_pending_del(SilcClientConnection conn,
+                                    SilcCommand reply_cmd,
+                                    unsigned short ident);
+int silc_client_command_pending_check(SilcClientConnection conn,
+                                     SilcClientCommandReplyContext ctx,
+                                     SilcCommand command, 
+                                     unsigned short ident);
 SILC_CLIENT_CMD_FUNC(whois);
 SILC_CLIENT_CMD_FUNC(whowas);
 SILC_CLIENT_CMD_FUNC(identify);
index a4e98d55d8180d51fdb9c1bb4cb5498abbecf177..51716566cbf05f438ea72fd3cb553fd07f375cad 100644 (file)
@@ -134,8 +134,11 @@ void silc_client_command_reply_process(SilcClient client,
                                       SilcPacketContext *packet)
 {
   SilcBuffer buffer = packet->buffer;
+  SilcClientCommandReply *cmd;
   SilcClientCommandReplyContext ctx;
   SilcCommandPayload payload;
+  SilcCommand command;
+  unsigned short ident;
 
   /* Get command reply payload from packet */
   payload = silc_command_payload_parse(buffer);
@@ -153,12 +156,24 @@ void silc_client_command_reply_process(SilcClient client,
   ctx->payload = payload;
   ctx->args = silc_command_get_args(ctx->payload);
   ctx->packet = packet;
+  ident = silc_command_get_ident(ctx->payload);
       
   /* Check for pending commands and mark to be exeucted */
-  SILC_CLIENT_COMMAND_CHECK_PENDING(ctx);
-  
+  silc_client_command_pending_check(sock->user_data, ctx, 
+                                   silc_command_get(ctx->payload), ident);
+
   /* Execute command reply */
-  SILC_CLIENT_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 || !cmd->cb) {
+    silc_free(ctx);
+    return;
+  }
+
+  cmd->cb(ctx);
 }
 
 /* Returns status message string */
@@ -332,6 +347,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
     silc_client_command_reply_whois_print(cmd, status);
   }
 
+  /* Execute any pending command callbacks */
   SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_WHOIS);
 
  out:
@@ -439,6 +455,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
 
   }
 
+  /* Execute any pending command callbacks */
   SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
 
  out:
@@ -483,6 +500,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick)
   /* Notify application */
   COMMAND_REPLY((ARGS, conn->local_entry));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_NICK);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -549,6 +569,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
   /* Notify application */
   COMMAND_REPLY((ARGS, channel, topic));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_TOPIC);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -575,6 +598,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_INVITE);
+
   silc_client_command_reply_free(cmd);
 }
  
@@ -624,6 +650,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
   /* Notify application */
   COMMAND_REPLY((ARGS, NULL, (char *)tmp));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_INFO);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -676,6 +705,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping)
 
   silc_free(id);
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_PING);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -774,6 +806,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
   COMMAND_REPLY((ARGS, channel_name, conn->current_channel, mode,
                 NULL, NULL, topic));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -834,6 +869,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd)
   /* Notify application */
   COMMAND_REPLY((ARGS, motd));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_MOTD);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -869,6 +907,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode)
   /* Notify application */
   COMMAND_REPLY((ARGS, tmp));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_CMODE);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -919,6 +960,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
   COMMAND_REPLY((ARGS, tmp, (SilcClientEntry)id_cache->context));
   silc_free(client_id);
   
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_CUMODE);
+
  out:
   silc_client_command_reply_free(cmd);
 }
@@ -964,6 +1008,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave)
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_LEAVE);
+
   silc_client_command_reply_free(cmd);
 }
 
@@ -982,11 +1029,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
   SilcBuffer client_id_list;
   SilcBuffer client_mode_list;
   unsigned char *tmp;
-  unsigned int tmp_len;
-  int i, k, len1, len2, list_count;
+  unsigned int tmp_len, list_count;
+  int i;
   unsigned char **res_argv = NULL;
   unsigned int *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0;
-  char *name_list, *cp;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -1094,59 +1140,46 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
   /* Query the client information from server if the list included clients
      that we don't know about. */
   if (res_argc) {
-#if 0
     SilcBuffer res_cmd;
 
+    /* Send the IDENTIFY command to server */
     res_cmd = silc_command_payload_encode(SILC_COMMAND_IDENTIFY,
                                          res_argc, res_argv, res_argv_lens,
-                                         res_argv_types, 0);
-    silc_client_packet_send(cmd->client, cmd->conn->sock,
-                           SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
-                           buffer->data, buffer->len, TRUE);
-    goto out;
-#endif
+                                         res_argv_types, ++conn->cmd_ident);
+    silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, 
+                           NULL, 0, NULL, NULL, res_cmd->data, res_cmd->len,
+                           TRUE);
+
+    /* Register pending command callback. After we've received the IDENTIFY
+       command reply we will reprocess this command reply by re-calling this
+       USERS command reply callback. */
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident,
+                               silc_client_command_reply_users, cmd);
+
+    silc_buffer_free(res_cmd);
+    if (channel_id)
+      silc_free(channel_id);
+
+    for (i = 0; i < res_argc; i++)
+      silc_free(res_argv[i]);
+    silc_free(res_argv);
+    silc_free(res_argv_lens);
+    silc_free(res_argv_types);
+    return;
   }
 
-  name_list = cp;
-  for (i = 0; i < list_count; i++) {
-    int c = 0;
-    int nick_len = strcspn(name_list, " ");
-    char *nickname = silc_calloc(nick_len + 1, sizeof(*nickname));
-    memcpy(nickname, name_list, nick_len);
-
-    silc_list_start(channel->clients);
-    while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
-      if (!strncmp(chu->client->nickname, nickname, 
-                  strlen(chu->client->nickname))) {
-       char t[8];
-       
-       if (!c) {
-         c++;
-         continue;
-       }
-       
-       memset(t, 0, sizeof(t));
-       chu->client->nickname = silc_calloc(strlen(nickname) + 8, 1);
-       snprintf(t, sizeof(t), "[%d]", c++);
-       strncat(chu->client->nickname, t, strlen(t));
-       strncat(chu->client->nickname, nickname, strlen(nickname));
-      }
-    }
-
-    silc_free(nickname);
-  }
+  /* We have all the clients on the channel cached now. Create a nice
+     output for user interface and notify application. */
 
-  /* XXX hmm... actually it is applications business to display this
-     information. We should just pass (as we do) the data to application and
-     let it to parse it and display it the way it wants. */
   if (cmd->callback) {
+    /* User has called USERS command on user interface. */
     cmd->client->ops->say(cmd->client, conn, "Users on %s", 
                          channel->channel_name);
     
     silc_list_start(channel->clients);
     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
       SilcClientEntry e = chu->client;
-      char *m, tmp[80], line[80];
+      char *m, tmp[80], line[80], len1;
 
       memset(line, 0, sizeof(line));
       memset(tmp, 0, sizeof(tmp));
@@ -1186,9 +1219,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
     }
 
   } else {
-    name_list = NULL;
-    len1 = 0;
-    k = 0;
+    /* Server has sent us USERS reply even when we haven't actually sent
+       USERS command. This is normal behaviour when joining to a channel.
+       Display some nice information on the user interface. */
+    int k = 0, len1 = 0, len2 = 0;
+    char *name_list = NULL;
 
     silc_list_start(channel->clients);
     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
@@ -1220,12 +1255,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
     silc_free(name_list);
   }
 
-  name_list = silc_argument_get_arg_type(cmd->args, 3, &len1);
-
   /* Notify application */
-  COMMAND_REPLY((ARGS, channel, name_list, client_id_list->head,
+  COMMAND_REPLY((ARGS, channel, client_id_list->head,
                 client_mode_list->head));
 
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_USERS);
+
   silc_buffer_free(client_id_list);
   silc_buffer_free(client_mode_list);
 
index 2b7acf7f346ee42578a4d2cceec007f2a1899350..c681ee4b80ea69a8517019276ba76d13c021d8a4 100644 (file)
@@ -40,7 +40,8 @@ typedef struct {
 
   /* If defined this executes the pending command. */
   void *context;
-  SilcClientCommandCallback callback;
+  SilcCommandCb callback;
+  unsigned short ident;
 } *SilcClientCommandReplyContext;
 
 /* Macros */
@@ -53,23 +54,6 @@ typedef struct {
 #define SILC_CLIENT_CMD_REPLY_FUNC(func) \
 void silc_client_command_reply_##func(void *context)
 
-/* Macro used to execute command replies */
-#define SILC_CLIENT_COMMAND_REPLY_EXEC(ctx)            \
-do {                                                   \
-  SilcClientCommandReply *cmd;                         \
-                                                       \
-  for (cmd = silc_command_reply_list; cmd->cb; cmd++)  \
-    if (cmd->cmd == silc_command_get(ctx->payload)) {  \
-      cmd->cb(ctx);                                    \
-      break;                                           \
-    }                                                  \
-                                                       \
-  if (cmd == NULL) {                                   \
-    silc_free(ctx);                                    \
-    return;                                            \
-  }                                                    \
-} while(0)
-
 /* Prototypes */
 void silc_client_command_reply_process(SilcClient client,
                                       SilcSocketConnection sock,
index 86689b092da0e004a7ef73c5c6e12db0d82481cc..cf1e8edc323fced42c033db0c138013223bb621b 100644 (file)
@@ -59,10 +59,10 @@ typedef unsigned char SilcPacketFlags;
 /* All defined packet flags */
 #define SILC_PACKET_FLAG_NONE             0x00
 #define SILC_PACKET_FLAG_PRIVMSG_KEY      0x01
-#define SILC_PACKET_FLAG_FORWARDED        0x02
-#define SILC_PACKET_FLAG_BROADCAST        0x04
-#define SILC_PACKET_FLAG_TUNNELED         0x08
+#define SILC_PACKET_FLAG_BROADCAST        0x02
+#define SILC_PACKET_FLAG_TUNNELED         0x04
 /* Rest of flags still available
+#define SILC_PACKET_FLAG_XXX              0x08
 #define SILC_PACKET_FLAG_XXX              0x10
 #define SILC_PACKET_FLAG_XXX              0x20
 #define SILC_PACKET_FLAG_XXX              0x40