updates.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 19 Feb 2001 13:47:30 +0000 (13:47 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 19 Feb 2001 13:47:30 +0000 (13:47 +0000)
18 files changed:
CHANGES
apps/silc/local_command.c
apps/silc/silc.c
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/command_reply.c
apps/silcd/command_reply.h
apps/silcd/idlist.h
apps/silcd/server_internal.h
apps/silcd/testi2.conf
lib/silcclient/client.c
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/command_reply.h
lib/silcclient/idlist.c
lib/silcclient/idlist.h
lib/silccore/silcpacket.c

diff --git a/CHANGES b/CHANGES
index 14b9cebdaed00349e7a4f2b6246be0ca5bb2627b..2b5c1b283771a8e620fe86a9bbad00984ed4e697 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,36 @@
+Mon Feb 19 14:26:49 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Changed SILC_SERVER_COMMAND_EXEC_PENDING macro to the name
+         SILC_SERVER_PENDING_EXEC and added an new macro
+         SILC_SERVER_PENDING_DESTRUCTOR which is called to free the
+         data or when error occurs while processing the pending command.
+
+         Added new argument `destructor' into silc_server_command_pending
+         and to the SilcServerCommandPending object.  This destructor is
+         now called after calling the pending callback or if error occurs
+         immediately.  If error occurs the actual pending callback won't
+         be called at all - only the destructor.  The destructor may be
+         NULL if destructor is not needed.
+
+         All this applies for client library code as well.  Similar
+         changes were made there as well for the pending commands.
+
+         In the client, the application must now allocate the 
+         SilcClientCommandContext with the silc_client_command_alloc
+         function.
+
+       * Added reference counter to the SilcServerCommandContext.  Added
+         function silc_server_command_alloc and silc_server_command_dup 
+         functions.
+
+         Same type of functions added to the client library for the same
+         purpose as well.
+
+       * Removed the cmd_ident from IDListData away since it is now 
+         global for all connections.  It is the command identifier used
+         in command sending and with pending commands.  The affected file
+         is silcd/idlist.h.
+
 Mon Feb 19 00:50:57 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Changed the client operation API: channel_message operation's
index 7a9316a5d4468d399f8375f06e0afc434b949d4b..b96c80d1e5f0259923bb7ad968dc6038692b1d14 100644 (file)
@@ -20,6 +20,9 @@
 /*
  * $Id$
  * $Log$
+ * Revision 1.5  2001/02/19 13:47:30  priikone
+ *     updates.
+ *
  * Revision 1.4  2001/02/16 00:33:23  priikone
  *     updates.
  *
@@ -146,7 +149,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(conn, SILC_COMMAND_IDENTIFY, 0,
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0, NULL,
                                silc_client_local_command_msg, context);
     return;
   }
index 203224cc900566229cd23798bd6a08ee937ee1e9..6a766e5750216c7889efd33c2114818341f211e3 100644 (file)
@@ -646,7 +646,7 @@ SILC_TASK_CALLBACK(silc_client_run_commands)
 
     /* Allocate command context. This and its internals must be free'd 
        by the command routine receiving it. */
-    ctx = silc_calloc(1, sizeof(*ctx));
+    ctx = silc_client_command_alloc();
     ctx->client = client;
     ctx->conn = app->conn;
     ctx->command = cmd;
index 95210f7d5cf0ca703fe2f554a9dec5d19c94d544..b018eaa12f22e6fc742ecc87b6687ae86eaf1479 100644 (file)
@@ -37,7 +37,6 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                     unsigned int arg_type,
                                     unsigned char *arg,
                                     unsigned int arg_len);
-static void silc_server_command_free(SilcServerCommandContext cmd);
 void silc_server_command_send_users(SilcServer server,
                                    SilcSocketConnection sock,
                                    SilcChannelEntry channel,
@@ -151,7 +150,7 @@ void silc_server_command_process(SilcServer server,
   
   /* Allocate command context. This must be free'd by the
      command routine receiving it. */
-  ctx = silc_calloc(1, sizeof(*ctx));
+  ctx = silc_server_command_alloc();
   ctx->server = server;
   ctx->sock = sock;
   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
@@ -189,6 +188,43 @@ void silc_server_command_process(SilcServer server,
   }
 }
 
+/* Allocate Command Context */
+
+SilcServerCommandContext silc_server_command_alloc()
+{
+  SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
+  ctx->users++;
+  return ctx;
+}
+
+/* Free's the command context allocated before executing the command */
+
+void silc_server_command_free(SilcServerCommandContext ctx)
+{
+  ctx->users--;
+  SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
+                 ctx->users));
+  if (ctx->users < 1) {
+    if (ctx->payload)
+      silc_command_free_payload(ctx->payload);
+    if (ctx->packet)
+      silc_packet_context_free(ctx->packet);
+    silc_free(ctx);
+  }
+}
+
+/* Duplicate Command Context by adding reference counter. The context won't
+   be free'd untill it hits zero. */
+
+SilcServerCommandContext 
+silc_server_command_dup(SilcServerCommandContext ctx)
+{
+  ctx->users++;
+  SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
+                 ctx->users));
+  return ctx;
+}
+
 /* 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
@@ -198,6 +234,7 @@ void silc_server_command_process(SilcServer server,
 void silc_server_command_pending(SilcServer server,
                                 SilcCommand reply_cmd,
                                 unsigned short ident,
+                                SilcServerPendingDestructor destructor,
                                 SilcCommandCb callback,
                                 void *context)
 {
@@ -208,6 +245,7 @@ void silc_server_command_pending(SilcServer server,
   reply->ident = ident;
   reply->context = context;
   reply->callback = callback;
+  reply->destructor = destructor;
   silc_dlist_add(server->pending_commands, reply);
 }
 
@@ -243,6 +281,7 @@ int silc_server_command_pending_check(SilcServer server,
     if (r->reply_cmd == command && r->ident == ident) {
       ctx->context = r->context;
       ctx->callback = r->callback;
+      ctx->destructor = r->destructor;
       ctx->ident = ident;
       return TRUE;
     }
@@ -251,17 +290,12 @@ int silc_server_command_pending_check(SilcServer server,
   return FALSE;
 }
 
-/* Free's the command context allocated before executing the command */
+/* Destructor function for pending callbacks. This is called when using
+   pending commands to free the context given for the pending command. */
 
-static void silc_server_command_free(SilcServerCommandContext cmd)
+static void silc_server_command_destructor(void *context)
 {
-  if (cmd) {
-    if (cmd->payload)
-      silc_command_free_payload(cmd->payload);
-    if (cmd->packet)
-      silc_packet_context_free(cmd->packet);
-    silc_free(cmd);
-  }
+  silc_server_command_free((SilcServerCommandContext)context);
 }
 
 /* Sends simple status message as command reply packet */
@@ -422,7 +456,9 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
       /* Reprocess this packet after received reply */
       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
                                  silc_command_get_ident(cmd->payload),
-                                 silc_server_command_whois, (void *)cmd);
+                                 silc_server_command_destructor,
+                                 silc_server_command_whois, 
+                                 silc_server_command_dup(cmd));
       cmd->pending = TRUE;
       
       silc_command_set_ident(cmd->payload, old_ident);
@@ -530,7 +566,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
   }
 }
 
-static int
+static void
 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -539,7 +575,7 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i, ret = 0;
+  int i;
 
   /* Protocol dictates that we must always send the received WHOIS request
      to our router if we are normal server, so let's do it now unless we
@@ -563,13 +599,14 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
     /* Reprocess this packet after received reply from router */
     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
                                silc_command_get_ident(cmd->payload),
-                               silc_server_command_whois, (void *)cmd);
+                               silc_server_command_destructor,
+                               silc_server_command_whois,
+                               silc_server_command_dup(cmd));
     cmd->pending = TRUE;
 
     silc_command_set_ident(cmd->payload, old_ident);
 
     silc_buffer_free(tmpbuf);
-    ret = -1;
     goto out;
   }
 
@@ -580,7 +617,7 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_WHOIS))
-    return 0;
+    return;
 
   /* Get all clients matching that ID or nickname from local list */
   if (client_id_count) {
@@ -641,10 +678,8 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
      mandatory fields that WHOIS command reply requires. Check for these and
      make query from the server who owns the client if some fields are 
      missing. */
-  if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
-    ret = -1;
+  if (!silc_server_command_whois_check(cmd, clients, clients_count))
     goto out;
-  }
 
   /* Send the command reply to the client */
   silc_server_command_whois_send_reply(cmd, clients, clients_count);
@@ -661,11 +696,9 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
-
-  return ret;
 }
 
-static int
+static void
 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -674,13 +707,13 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i, ret = 0;
+  int i;
 
   /* Parse the whois request */
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_WHOIS))
-    return 0;
+    return;
 
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
@@ -751,10 +784,8 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
      mandatory fields that WHOIS command reply requires. Check for these and
      make query from the server who owns the client if some fields are 
      missing. */
-  if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
-    ret = -1;
+  if (!silc_server_command_whois_check(cmd, clients, clients_count))
     goto out;
-  }
 
   /* Send the command reply to the client */
   silc_server_command_whois_send_reply(cmd, clients, clients_count);
@@ -771,8 +802,6 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
-
-  return ret;
 }
 
 /* Server side of command WHOIS. Processes user's query and sends found 
@@ -781,17 +810,15 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
 SILC_SERVER_CMD_FUNC(whois)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  int ret;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
-    ret = silc_server_command_whois_from_client(cmd);
+    silc_server_command_whois_from_client(cmd);
   else
-    ret = silc_server_command_whois_from_server(cmd);
+    silc_server_command_whois_from_server(cmd);
 
-  if (!ret)
-    silc_server_command_free(cmd);
+  silc_server_command_free(cmd);
 }
 
 SILC_SERVER_CMD_FUNC(whowas)
@@ -841,7 +868,10 @@ silc_server_command_identify_check(SilcServerCommandContext cmd,
       /* Reprocess this packet after received reply */
       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
                                  silc_command_get_ident(cmd->payload),
-                                 silc_server_command_identify, (void *)cmd);
+                                 silc_server_command_destructor,
+                                 silc_server_command_identify,
+                                 silc_server_command_dup(cmd));
+
       cmd->pending = TRUE;
       
       /* Put old data back to the Command Payload we just changed */
@@ -936,7 +966,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
   }
 }
 
-static int
+static void
 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -945,7 +975,7 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i, ret = 0;
+  int i;
 
   /* Protocol dictates that we must always send the received IDENTIFY request
      to our router if we are normal server, so let's do it now unless we
@@ -969,13 +999,14 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
     /* Reprocess this packet after received reply from router */
     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
                                silc_command_get_ident(cmd->payload),
-                               silc_server_command_identify, (void *)cmd);
+                               silc_server_command_destructor,
+                               silc_server_command_identify,
+                               silc_server_command_dup(cmd));
     cmd->pending = TRUE;
 
     silc_command_set_ident(cmd->payload, old_ident);
 
     silc_buffer_free(tmpbuf);
-    ret = -1;
     goto out;
   }
 
@@ -986,7 +1017,7 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_IDENTIFY))
-    return 0;
+    return;
 
   /* Get all clients matching that ID or nickname from local list */
   if (client_id_count) { 
@@ -1044,10 +1075,8 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
 
   /* Check that all mandatory fields are present and request those data
      from the server who owns the client if necessary. */
-  if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
-    ret = -1;
+  if (!silc_server_command_identify_check(cmd, clients, clients_count))
     goto out;
-  }
 
   /* Send the command reply to the client */
   silc_server_command_identify_send_reply(cmd, clients, clients_count);
@@ -1064,11 +1093,9 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
-
-  return ret;
 }
 
-static int
+static void
 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -1077,13 +1104,13 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i, ret = 0;
+  int i;
 
   /* Parse the IDENTIFY request */
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_IDENTIFY))
-    return 0;
+    return;
 
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
@@ -1151,10 +1178,8 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 
   /* Check that all mandatory fields are present and request those data
      from the server who owns the client if necessary. */
-  if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
-    ret = -1;
+  if (!silc_server_command_identify_check(cmd, clients, clients_count))
     goto out;
-  }
 
   /* Send the command reply */
   silc_server_command_identify_send_reply(cmd, clients, clients_count);
@@ -1171,24 +1196,20 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
-
-  return ret;
 }
 
 SILC_SERVER_CMD_FUNC(identify)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  int ret;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
-    ret = silc_server_command_identify_from_client(cmd);
+    silc_server_command_identify_from_client(cmd);
   else
-    ret = silc_server_command_identify_from_server(cmd);
+    silc_server_command_identify_from_server(cmd);
 
-  if (!ret)
-    silc_server_command_free(cmd);
+  silc_server_command_free(cmd);
 }
 
 /* Checks string for bad characters and returns TRUE if they are found. */
@@ -1686,7 +1707,7 @@ void silc_server_command_send_users(SilcServer server,
   packet->sock = sock;
   packet->type = SILC_PACKET_COMMAND;
 
-  cmd = silc_calloc(1, sizeof(*cmd));
+  cmd = silc_server_command_alloc();
   cmd->payload = silc_command_payload_parse(buffer);
   if (!cmd->payload) {
     silc_free(cmd);
@@ -1707,16 +1728,17 @@ void silc_server_command_send_users(SilcServer server,
        will process it after we've received the automatic USERS command 
        reply. */
     silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
-                               silc_server_command_users, (void *)cmd);
+                               silc_server_command_destructor,
+                               silc_server_command_users,
+                               silc_server_command_dup(cmd));
     cmd->pending = TRUE;
-    silc_buffer_free(buffer);
-    silc_buffer_free(idp);
-    return;
+    goto out;
   }
 
   /* Process USERS command. */
   silc_server_command_users((void *)cmd);
+
+ out:
   silc_buffer_free(buffer);
   silc_buffer_free(idp);
   silc_packet_context_free(packet);
@@ -2010,9 +2032,11 @@ SILC_SERVER_CMD_FUNC(join)
          /* Reprocess this packet after received reply from router */
          silc_server_command_pending(server, SILC_COMMAND_JOIN, 
                                      silc_command_get_ident(cmd->payload),
-                                     silc_server_command_join, context);
+                                     silc_server_command_destructor,
+                                     silc_server_command_join,
+                                     silc_server_command_dup(cmd));
          cmd->pending = TRUE;
-         return;
+         goto out;
        }
        
        /* We are router and the channel does not seem exist so we will check
@@ -2891,13 +2915,15 @@ SILC_SERVER_CMD_FUNC(users)
       /* Reprocess this packet after received reply */
       silc_server_command_pending(server, SILC_COMMAND_USERS, 
                                  silc_command_get_ident(cmd->payload),
-                                 silc_server_command_users, (void *)cmd);
+                                 silc_server_command_destructor,
+                                 silc_server_command_users,
+                                 silc_server_command_dup(cmd));
       cmd->pending = TRUE;
       silc_command_set_ident(cmd->payload, ident);
       
       silc_buffer_free(tmpbuf);
       silc_free(id);
-      return;
+      goto out;
     }
 
     /* We are router and we will check the global list as well. */
index de0b464b78d02f3fd28d93f0ee97ee26964ae64e..9180768a213efafdd7a0a8b635a7c2c2f1897aea 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef COMMAND_H
 #define COMMAND_H
 
-#include "command_reply.h"
-
 /* 
    Structure holding one command and pointer to its function. 
 
@@ -57,19 +55,30 @@ typedef struct {
   SilcArgumentPayload args;
   SilcPacketContext *packet;
   int pending;                 /* Command is being re-processed when TRUE */
+  int users;                   /* Reference counter */
 } *SilcServerCommandContext;
 
+/* Pending Command callback destructor. This is called after calling the
+   pending callback or if error occurs while processing the pending command.
+   If error occurs then the callback won't be called at all, and only this
+   destructor is called. The `context' is the context given for the function
+   silc_server_command_pending. */
+typedef void (*SilcServerPendingDestructor)(void *context);
+
 /* Structure holding pending commands. If command is pending it will be
    executed after command reply has been received and executed. */
 typedef struct SilcServerCommandPendingStruct {
   SilcServer server;
   SilcCommand reply_cmd;
   SilcCommandCb callback;
+  SilcServerPendingDestructor destructor;
   void *context;
   unsigned short ident;
   struct SilcServerCommandPendingStruct *next;
 } SilcServerCommandPending;
 
+#include "command_reply.h"
+
 /* Macros */
 
 /* Macro used for command declaration in command list structure */
@@ -81,21 +90,32 @@ typedef struct SilcServerCommandPendingStruct {
 void silc_server_command_##func(void *context)
 
 /* Executed pending command */
-#define SILC_SERVER_COMMAND_EXEC_PENDING(ctx, cmd)                     \
+#define SILC_SERVER_PENDING_EXEC(ctx, cmd)                             \
 do {                                                                   \
-  if (ctx->callback) {                                                 \
+  if (ctx->callback)                                                   \
     (*ctx->callback)(ctx->context);                                    \
-    silc_server_command_pending_del(ctx->server, cmd, ctx->ident);     \
-  }                                                                    \
+} while(0)
+
+/* Execute destructor for pending command */
+#define SILC_SERVER_PENDING_DESTRUCTOR(ctx, cmd)                       \
+do {                                                                   \
+  silc_server_command_pending_del(ctx->server, cmd, ctx->ident);       \
+  if (ctx->destructor)                                                 \
+    (*ctx->destructor)(ctx->context);                                  \
 } while(0)
 
 /* Prototypes */
 void silc_server_command_process(SilcServer server,
                                 SilcSocketConnection sock,
                                 SilcPacketContext *packet);
+SilcServerCommandContext silc_server_command_alloc();
+void silc_server_command_free(SilcServerCommandContext ctx);
+SilcServerCommandContext 
+silc_server_command_dup(SilcServerCommandContext ctx);
 void silc_server_command_pending(SilcServer server,
                                 SilcCommand reply_cmd,
                                 unsigned short ident,
+                                SilcServerPendingDestructor destructor,
                                 SilcCommandCb callback,
                                 void *context);
 void silc_server_command_pending_del(SilcServer server,
index bc73928ad24a2b57590e9f2c84fcb82230fdbf28..8e99cb38158de0f0cc355a7e2459643fdf20cb72 100644 (file)
@@ -231,9 +231,10 @@ SILC_SERVER_CMD_REPLY_FUNC(whois)
     goto out;
 
   /* Execute any pending commands */
-  SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_WHOIS);
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
 
  out:
+  SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
   silc_server_command_reply_free(cmd);
 }
 
@@ -350,9 +351,10 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
     goto out;
 
   /* Execute any pending commands */
-  SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
 
  out:
+  SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
   silc_server_command_reply_free(cmd);
 }
 
@@ -451,9 +453,10 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   silc_buffer_free(keyp);
 
   /* Execute any pending commands */
-  SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
 
  out:
+  SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
   silc_server_command_reply_free(cmd);
 }
 
@@ -577,9 +580,10 @@ SILC_SERVER_CMD_REPLY_FUNC(users)
   silc_buffer_free(client_mode_list);
 
   /* Execute any pending commands */
-  SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_USERS);
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
 
  out:
+  SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
   if (channel_id)
     silc_free(channel_id);
   silc_server_command_reply_free(cmd);
index 62a696e81b5ec341d1b62ae15659f033fa292147..4c6b63eb399f66d80908507cdb176a78fa7f93df 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef COMMAND_REPLY_H
 #define COMMAND_REPLY_H
 
+#include "command.h"
+
 /* Structure holding one command reply and pointer to its function. */
 typedef struct {
   SilcCommandCb cb;
@@ -38,8 +40,9 @@ typedef struct {
   SilcArgumentPayload args;
 
   /* If defined this executes the pending command. */
-  void *context;
+  SilcServerPendingDestructor destructor;
   SilcCommandCb callback;
+  void *context;
   unsigned short ident;
 } *SilcServerCommandReplyContext;
 
index 4940b6c8cdbe0d7b455e6913c45a509ebc61bd7b..c9ce8cf6ef59ff57ca415b27f8e19a29eae02550 100644 (file)
@@ -53,7 +53,6 @@ typedef struct {
   SilcPKCS pkcs;
   SilcPublicKey public_key;
 
-  unsigned short cmd_ident;  /* Current command identifier, 0 not used */
   long last_receive;         /* Time last received data */
   long last_sent;           /* Time last sent data */
   unsigned char registered;  /* Boolean whether connection is registered */
index 346162798eda045b8fb42bc5dfe5a4363234eccc..0e1ac428af554ac03eaf7bc2c305bf6276a17bf0 100644 (file)
@@ -87,6 +87,9 @@ struct SilcServerStruct {
   unsigned int id_string_len;
   SilcIdType id_type;
 
+  /* Current command identifier, 0 not used */
+  unsigned short cmd_ident;
+
   /* Server's own ID entry. */
   SilcServerEntry id_entry;
 
index 35f54730a3ecf478eca431e08f08df91aa359faf..fe6247a1d0a8b9ff75a693d83810e3924412a3a0 100644 (file)
@@ -19,10 +19,10 @@ nobody:nobody
 Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
 
 [ServerInfo]
-lassi.kuo.fi.ssh.com:212.146.8.245:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
 
 [ListenPort]
-212.146.8.245:212.146.8.245:1334
+10.2.1.7:10.2.1.7:1334
 
 [Logging]
 infologfile:silcd2.log:10000
@@ -43,10 +43,10 @@ errorlogfile:silcd2.log:10000
 [AdminConnection]
 
 [ServerConnection]
-212.146.8.245:passwd:priikone:1333:1:1
+10.2.1.7:passwd:priikone:1333:1:1
 
 [RouterConnection]
-212.146.8.245:passwd:priikone:1335:1:1:0
+10.2.1.7:passwd:priikone:1335:1:1:0
 
 [DenyConnection]
 [RedirectClient]
index b40bd47fbd1e8e1fb8aaba220e3acbfda5e66a8e..b931b51c7a2b89474d47c60c1ee6a9a66dda4ac1 100644 (file)
@@ -1281,7 +1281,34 @@ static void silc_client_notify_by_server_pending(void *context)
 {
   SilcPacketContext *p = (SilcPacketContext *)context;
   silc_client_notify_by_server(p->context, p->sock, p);
-  silc_packet_context_free(p);
+}
+
+/* Destructor for the pending command callback */
+
+static void silc_client_notify_by_server_destructor(void *context)
+{
+  silc_packet_context_free((SilcPacketContext *)context);
+}
+
+/* Resolve client information from server by Client ID. */
+
+static void silc_client_notify_by_server_resolve(SilcClient client,
+                                                SilcClientConnection conn,
+                                                SilcPacketContext *packet,
+                                                SilcClientID *client_id)
+{
+  SilcPacketContext *p = silc_packet_context_dup(packet);
+  SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+
+  p->context = (void *)client;
+  p->sock = conn->sock;
+
+  silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
+                          1, 3, idp->data, idp->len);
+  silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
+                             silc_client_notify_by_server_destructor,
+                             silc_client_notify_by_server_pending, p);
+  silc_buffer_free(idp);
 }
 
 /* Received notify message from server */
@@ -1338,13 +1365,9 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
 
     /* Find Client entry and if not found query it */
-    client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
+    client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry) {
-      SilcPacketContext *p = silc_packet_context_dup(packet);
-      p->context = (void *)client;
-      p->sock = sock;
-      silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
-                                 silc_client_notify_by_server_pending, p);
+      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
       goto out;
     }
 
@@ -1388,27 +1411,15 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
 
     /* Find Client entry and if not found query it */
-    client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
+    client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry) {
-      SilcPacketContext *p = silc_packet_context_dup(packet);
-      p->context = (void *)client;
-      p->sock = sock;
-      silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT, 
-                                 silc_client_notify_by_server_pending, p);
+      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
       goto out;
     }
 
     /* If nickname or username hasn't been resolved, do so */
     if (!client_entry->nickname || !client_entry->username) {
-      SilcPacketContext *p = silc_packet_context_dup(packet);
-      SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
-      silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, 
-                              SILC_IDLIST_IDENT, 1, 
-                              3, idp->data, idp->len);
-      p->context = (void *)client;
-      p->sock = sock;
-      silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT, 
-                                 silc_client_notify_by_server_pending, p);
+      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
       goto out;
     }
 
@@ -1454,7 +1465,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find Client entry */
     client_entry = 
-      silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry)
       goto out;
 
@@ -1501,7 +1512,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find Client entry */
     client_entry = 
-      silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry)
       goto out;
 
@@ -1544,7 +1555,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find Client entry */
     client_entry = 
-      silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry)
       goto out;
 
@@ -1593,13 +1604,9 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find Client entry and if not found query it */
     client_entry2 = 
-      silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry2) {
-      SilcPacketContext *p = silc_packet_context_dup(packet);
-      p->context = (void *)client;
-      p->sock = sock;
-      silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
-                                 silc_client_notify_by_server_pending, p);
+      silc_client_notify_by_server_resolve(client, conn, packet, client_id);
       goto out;
     }
     silc_free(client_id);
@@ -1615,7 +1622,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find old Client entry */
     client_entry = 
-      silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry)
       goto out;
 
@@ -1659,7 +1666,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find Client entry */
     client_entry = 
-      silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry)
       goto out;
 
@@ -1706,7 +1713,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find Client entry */
     client_entry = 
-      silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry)
       goto out;
 
@@ -1729,7 +1736,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Find target Client entry */
     client_entry2 = 
-      silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
+      silc_idlist_get_client_by_id(client, conn, client_id);
     if (!client_entry2)
       goto out;
 
index 16990b38cf0c592e3e1beec45ad1b9a70a795f0c..245a81f9825f44056eade785168fa7d784834d05 100644 (file)
@@ -117,6 +117,7 @@ SilcClientCommand *silc_client_command_find(const char *name)
 void silc_client_command_pending(SilcClientConnection conn,
                                 SilcCommand reply_cmd,
                                 unsigned short ident,
+                                SilcClientPendingDestructor destructor,
                                 SilcCommandCb callback,
                                 void *context)
 {
@@ -127,6 +128,7 @@ void silc_client_command_pending(SilcClientConnection conn,
   reply->ident = ident;
   reply->context = context;
   reply->callback = callback;
+  reply->destructor = destructor;
   silc_dlist_add(conn->pending_commands, reply);
 }
 
@@ -162,6 +164,7 @@ int silc_client_command_pending_check(SilcClientConnection conn,
     if (r->reply_cmd == command && r->ident == ident) {
       ctx->context = r->context;
       ctx->callback = r->callback;
+      ctx->destructor = r->destructor;
       ctx->ident = ident;
       return TRUE;
     }
@@ -170,19 +173,50 @@ int silc_client_command_pending_check(SilcClientConnection conn,
   return FALSE;
 }
 
+/* Allocate Command Context */
+
+SilcClientCommandContext silc_client_command_alloc()
+{
+  SilcClientCommandContext ctx = silc_calloc(1, sizeof(*ctx));
+  ctx->users++;
+  return ctx;
+}
+
 /* Free command context and its internals */
 
-void silc_client_command_free(SilcClientCommandContext cmd)
+void silc_client_command_free(SilcClientCommandContext ctx)
 {
-  int i;
+  ctx->users--;
+  SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
+                 ctx->users));
+  if (ctx->users < 1) {
+    int i;
 
-  if (cmd) {
-    for (i = 0; i < cmd->argc; i++)
-      silc_free(cmd->argv[i]);
-    silc_free(cmd);
+    for (i = 0; i < ctx->argc; i++)
+      silc_free(ctx->argv[i]);
+    silc_free(ctx);
   }
 }
 
+/* Duplicate Command Context by adding reference counter. The context won't
+   be free'd untill it hits zero. */
+
+SilcClientCommandContext 
+silc_client_command_dup(SilcClientCommandContext ctx)
+{
+  ctx->users++;
+  SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
+                 ctx->users));
+  return ctx;
+}
+
+/* Pending command destructor. */
+
+static void silc_client_command_destructor(void *context)
+{
+  silc_client_command_free((SilcClientCommandContext)context);
+}
+
 /* Command WHOIS. This command is used to query information about 
    specific user. */
 
@@ -447,8 +481,10 @@ SILC_CLIENT_CMD_FUNC(invite)
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
     silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0,
-                               silc_client_command_invite, context);
-    return;
+                               silc_client_command_destructor,
+                               silc_client_command_invite, 
+                               silc_client_command_dup(cmd));
+    goto out;
   }
 
   /* Find channel entry */
@@ -996,8 +1032,10 @@ SILC_CLIENT_CMD_FUNC(cumode)
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
     silc_client_command_pending(conn, SILC_COMMAND_CUMODE, 0,  
-                               silc_client_command_cumode, context);
-    return;
+                               silc_client_command_destructor,
+                               silc_client_command_cumode, 
+                               silc_client_command_dup(cmd));
+    goto out;
   }
   
   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
@@ -1238,9 +1276,11 @@ SILC_CLIENT_CMD_FUNC(users)
        same context and reprocesses the command. When reprocessing we actually
        display the information on the screen. */
     silc_client_command_pending(conn, SILC_COMMAND_USERS, 0, 
-                               silc_client_command_users, context);
+                               silc_client_command_destructor,
+                               silc_client_command_users, 
+                               silc_client_command_dup(cmd));
     cmd->pending = TRUE;
-    return;
+    goto out;
   }
 
   if (cmd->pending) {
index 632f957afca39864c5e3fc566f39a64c66871bea..cf236483e51669995812f32c21537ff07aebd56a 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef COMMAND_H
 #define COMMAND_H
 
-#include "command_reply.h"
-
 /* 
    Structure holding one command and pointer to its function. 
 
@@ -71,13 +69,22 @@ typedef struct {
   unsigned int *argv_lens;
   unsigned int *argv_types;
   int pending;                 /* Command is being re-processed when TRUE */
+  int users;                   /* Reference counter */
 } *SilcClientCommandContext;
 
+/* Pending Command callback destructor. This is called after calling the
+   pending callback or if error occurs while processing the pending command.
+   If error occurs then the callback won't be called at all, and only this
+   destructor is called. The `context' is the context given for the function
+   silc_client_command_pending. */
+typedef void (*SilcClientPendingDestructor)(void *context);
+
 /* Structure holding pending commands. If command is pending it will be
    executed after command reply has been executed. */
 typedef struct SilcClientCommandPendingStruct {
   SilcCommand reply_cmd;
   SilcCommandCb callback;
+  SilcClientPendingDestructor destructor;
   void *context;
   unsigned short ident;
   struct SilcClientCommandPendingStruct *next;
@@ -86,6 +93,8 @@ typedef struct SilcClientCommandPendingStruct {
 /* List of pending commands */
 extern SilcClientCommandPending *silc_command_pending;
 
+#include "command_reply.h"
+
 /* Macros */
 
 /* Macro used for command declaration in command list structure */
@@ -97,24 +106,34 @@ extern SilcClientCommandPending *silc_command_pending;
 void silc_client_command_##func(void *context)
 
 /* Executed pending command callback */
-#define SILC_CLIENT_COMMAND_EXEC_PENDING(ctx, cmd)                     \
+#define SILC_CLIENT_PENDING_EXEC(ctx, cmd)     \
+do {                                           \
+  if ((ctx)->callback)                         \
+    (*ctx->callback)(ctx->context);            \
+} while(0)
+
+/* Execute destructor for pending command */
+#define SILC_CLIENT_PENDING_DESTRUCTOR(ctx, cmd)                       \
 do {                                                                   \
-  if ((ctx)->callback) {                                               \
-    (*ctx->callback)(ctx->context);                                    \
-    silc_client_command_pending_del((ctx)->sock->user_data, (cmd),     \
-                                   (ctx)->ident);                      \
-  }                                                                    \
+  silc_client_command_pending_del((ctx)->sock->user_data, (cmd),       \
+                                 (ctx)->ident);                        \
+  if (ctx->destructor)                                                 \
+    (*ctx->destructor)(ctx->context);                                  \
 } while(0)
 
 /* Prototypes */
-void silc_client_command_free(SilcClientCommandContext cmd);
 void silc_client_send_command(SilcClient client, SilcClientConnection conn,
                              SilcCommand command, unsigned short ident,
                              unsigned int argc, ...);
 SilcClientCommand *silc_client_command_find(const char *name);
+SilcClientCommandContext silc_client_command_alloc();
+void silc_client_command_free(SilcClientCommandContext ctx);
+SilcClientCommandContext 
+silc_client_command_dup(SilcClientCommandContext ctx);
 void silc_client_command_pending(SilcClientConnection conn,
                                 SilcCommand reply_cmd,
                                 unsigned short ident,
+                                SilcClientPendingDestructor destructor,
                                 SilcCommandCb callback,
                                 void *context);
 void silc_client_command_pending_del(SilcClientConnection conn,
index 48e1a70525601f693d390ec3a752295a7162f704..2c576730fa6eab1536abf710e5ce35f002377f61 100644 (file)
@@ -353,9 +353,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
   }
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_WHOIS);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
   silc_client_command_reply_free(cmd);
 }
 
@@ -464,9 +465,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
   }
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
   silc_client_command_reply_free(cmd);
 }
 
@@ -513,9 +515,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick)
   COMMAND_REPLY((ARGS, conn->local_entry));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_NICK);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_NICK);
   silc_client_command_reply_free(cmd);
 }
 
@@ -542,6 +545,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
     cmd->client->ops->say(cmd->client, conn,
             "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
+    SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_TOPIC);
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -584,9 +588,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
   COMMAND_REPLY((ARGS, channel, topic));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_TOPIC);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_TOPIC);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_TOPIC);
   silc_client_command_reply_free(cmd);
 }
 
@@ -605,6 +610,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
     cmd->client->ops->say(cmd->client, conn,
             "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
+    SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE);
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -613,8 +619,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
   COMMAND_REPLY((ARGS));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_INVITE);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INVITE);
 
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE);
   silc_client_command_reply_free(cmd);
 }
  
@@ -643,6 +650,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
     cmd->client->ops->say(cmd->client, conn,
             "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
+    SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
     silc_client_command_reply_free(cmd);
     return;
   }
@@ -665,9 +673,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
   COMMAND_REPLY((ARGS, NULL, (char *)tmp));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_INFO);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
   silc_client_command_reply_free(cmd);
 }
 
@@ -725,9 +734,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping)
   COMMAND_REPLY((ARGS));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_PING);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PING);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_PING);
   silc_client_command_reply_free(cmd);
 }
 
@@ -831,9 +841,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
                 NULL, NULL, topic));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
   silc_client_command_reply_free(cmd);
 }
 
@@ -894,9 +905,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd)
   COMMAND_REPLY((ARGS, motd));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_MOTD);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
   silc_client_command_reply_free(cmd);
 }
 
@@ -932,9 +944,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode)
   COMMAND_REPLY((ARGS, tmp));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_CMODE);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CMODE);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CMODE);
   silc_client_command_reply_free(cmd);
 }
 
@@ -989,9 +1002,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
   silc_free(client_id);
   
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_CUMODE);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CUMODE);
 
  out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CUMODE);
   silc_client_command_reply_free(cmd);
 }
 
@@ -1030,15 +1044,17 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave)
     cmd->client->ops->say(cmd->client, conn,
             "%s", silc_client_command_status_message(status));
     COMMAND_REPLY_ERROR;
-    return;
+    goto out;
   }
 
   /* Notify application */
   COMMAND_REPLY((ARGS));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_LEAVE);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LEAVE);
 
+ out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_LEAVE);
   silc_client_command_reply_free(cmd);
 }
 
@@ -1187,7 +1203,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
        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);
+                               NULL, silc_client_command_reply_users, cmd);
 
     silc_buffer_free(res_cmd);
     if (channel_id)
@@ -1244,7 +1260,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
                 client_mode_list->head));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_USERS);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
 
   silc_buffer_free(client_id_list);
   silc_buffer_free(client_mode_list);
@@ -1252,5 +1268,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
  out:
   if (channel_id)
     silc_free(channel_id);
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
   silc_client_command_reply_free(cmd);
 }
index c681ee4b80ea69a8517019276ba76d13c021d8a4..2bd274baeaa26bceeba38f557052886a7463cfb9 100644 (file)
@@ -39,8 +39,9 @@ typedef struct {
   SilcPacketContext *packet;
 
   /* If defined this executes the pending command. */
-  void *context;
+  SilcClientPendingDestructor destructor;
   SilcCommandCb callback;
+  void *context;
   unsigned short ident;
 } *SilcClientCommandReplyContext;
 
index 3adc43eb3ae20cc49a17381a3734222b6f1ed804..e3f30554abd06c806eec8b4fa1ecb4482f7d52ef 100644 (file)
@@ -48,7 +48,7 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
 
     /* No ID found. Do query from the server. The query is done by 
        sending simple IDENTIFY command to the server. */
-    ctx = silc_calloc(1, sizeof(*ctx));
+    ctx = silc_client_command_alloc();
     ctx->client = client;
     ctx->conn = conn;
     ctx->command = silc_client_command_find("IDENTIFY");
@@ -102,13 +102,11 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
   return entry;
 }
 
-/* Finds client entry from cache by Client ID. If the entry is not found
-   from the cache this function can query it from the server. */
+/* Finds client entry from cache by Client ID. */
 
 SilcClientEntry silc_idlist_get_client_by_id(SilcClient client,
                                             SilcClientConnection conn,
-                                            SilcClientID *client_id,
-                                            int query)
+                                            SilcClientID *client_id)
 {
   SilcIDCacheEntry id_cache;
 
@@ -117,17 +115,8 @@ SilcClientEntry silc_idlist_get_client_by_id(SilcClient client,
 
   /* Find ID from cache */
   if (!silc_idcache_find_by_id_one(conn->client_cache, client_id, 
-                                  SILC_ID_CLIENT, &id_cache)) {
-    if (!query) {
-      return NULL;
-    } else {
-      SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
-      silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, 
-                              SILC_IDLIST_IDENT, 1, 
-                              3, idp->data, idp->len);
-      return NULL;
-    }
-  }
+                                  SILC_ID_CLIENT, &id_cache))
+    return NULL;
 
   return (SilcClientEntry)id_cache->context;
 }
index 1e12686ce90d073cd52d9eee57b3c1dedef0dadf..543d745f2ac5a59204fccf13340422546e106771 100644 (file)
@@ -79,8 +79,7 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
                                       unsigned int num);
 SilcClientEntry silc_idlist_get_client_by_id(SilcClient client,
                                             SilcClientConnection conn,
-                                            SilcClientID *client_id,
-                                            int query);
+                                            SilcClientID *client_id);
 SilcChannelEntry silc_idlist_get_channel(SilcClient client,
                                         SilcClientConnection conn,
                                         char *channel);
index 5b9d33e30f3d3de88fc78cac4d09f9641ee3b39b..4f003c668b52621d9e5620044c791ad22a325e82 100644 (file)
@@ -751,7 +751,7 @@ SilcPacketContext *silc_packet_context_alloc()
 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
 {
   ctx->users++;
-  SILC_LOG_DEBUG(("Packet context %p rfcnt %d->%d", ctx, ctx->users - 1,
+  SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
                  ctx->users));
   return ctx;
 }
@@ -762,7 +762,7 @@ SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
 void silc_packet_context_free(SilcPacketContext *ctx)
 {
   ctx->users--;
-  SILC_LOG_DEBUG(("Packet context %p rfcnt %d->%d", ctx, ctx->users + 1,
+  SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
                  ctx->users));
   if (ctx->users < 1)
     {