CONNECT, CLOSE and SHUTDOWN commands.
[silc.git] / lib / silcclient / command.h
index 7e7db0e9a32b2b8ef90dc8e7078fffbde90ccf7d..a47c7461f420a0edc6f6bacbda15544e86a451b4 100644 (file)
@@ -59,10 +59,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;
@@ -72,23 +68,33 @@ typedef struct {
   unsigned char **argv;
   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. */
-/* XXX This support may added for commands as well and not just command
-   replies, if needed later. */
 typedef struct SilcClientCommandPendingStruct {
   SilcCommand reply_cmd;
+  SilcCommandCb callback;
+  SilcClientPendingDestructor destructor;
   void *context;
-  SilcClientCommandCallback callback;
-
+  unsigned short ident;
   struct SilcClientCommandPendingStruct *next;
 } SilcClientCommandPending;
 
 /* List of pending commands */
 extern SilcClientCommandPending *silc_command_pending;
 
+#include "command_reply.h"
+
 /* Macros */
 
 /* Macro used for command declaration in command list structure */
@@ -99,42 +105,44 @@ 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;                                          \
-      }                                                        \
-    }                                                  \
-  }                                                    \
+/* Executed pending command callback */
+#define SILC_CLIENT_PENDING_EXEC(ctx, cmd)     \
+do {                                           \
+  if ((ctx)->callback)                         \
+    (*ctx->callback)(ctx->context);            \
 } 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));            \
-  }                                                    \
+/* Execute destructor for pending command */
+#define SILC_CLIENT_PENDING_DESTRUCTOR(ctx, cmd)                       \
+do {                                                                   \
+  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 int argc, ...);
+                             SilcCommand command, unsigned short ident,
+                             unsigned int argc, ...);
 SilcClientCommand *silc_client_command_find(const char *name);
-void silc_client_command_pending(SilcCommand reply_cmd,
-                                SilcClientCommandCallback callback,
+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(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);
@@ -156,7 +164,7 @@ SILC_CLIENT_CMD_FUNC(cumode);
 SILC_CLIENT_CMD_FUNC(kick);
 SILC_CLIENT_CMD_FUNC(restart);
 SILC_CLIENT_CMD_FUNC(close);
-SILC_CLIENT_CMD_FUNC(die);
+SILC_CLIENT_CMD_FUNC(shutdown);
 SILC_CLIENT_CMD_FUNC(silcoper);
 SILC_CLIENT_CMD_FUNC(leave);
 SILC_CLIENT_CMD_FUNC(users);