Moved the SilcClient and SilcClientConnection to the public
[silc.git] / lib / silcclient / client_resume.c
index 0d0d24ba7b19b4f393ec48b2d04d556617098a9e..5f1cced0181e16ba2a961337738572356b06ea3b 100644 (file)
@@ -27,6 +27,15 @@ SILC_CLIENT_CMD_FUNC(resume_identify);
 SILC_CLIENT_CMD_FUNC(resume_cmode);
 SILC_CLIENT_CMD_FUNC(resume_users);
 
+#define RESUME_CALL_COMPLETION(client, session, s)                     \
+do {                                                                   \
+  SILC_LOG_DEBUG(("Calling completion"));                              \
+  session->success = s;                                                        \
+  silc_schedule_task_add(client->schedule, 0,                          \
+                        silc_client_resume_call_completion, session,   \
+                        0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);   \
+} while(0)
+
 /* Generates the session detachment data. This data can be used later
    to resume back to the server. */
 
@@ -105,8 +114,8 @@ bool silc_client_process_detach_data(SilcClient client,
   SILC_LOG_DEBUG(("Start"));
 
   silc_free(conn->nickname);
-  silc_buffer_set(&detach, conn->params.detach_data, 
-                 conn->params.detach_data_len);
+  silc_buffer_set(&detach, conn->internal->params.detach_data, 
+                 conn->internal->params.detach_data_len);
 
   SILC_LOG_HEXDUMP(("Detach data"), detach.data, detach.len);
 
@@ -157,17 +166,6 @@ bool silc_client_process_detach_data(SilcClient client,
   return TRUE;
 }
 
-/* Generic command reply callback */
-
-SILC_CLIENT_CMD_REPLY_FUNC(resume)
-{
-  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  if (cmd->callback)
-    (*cmd->callback)(cmd->context, cmd);
-}
 
 /* Resume session context */
 typedef struct {
@@ -176,8 +174,55 @@ typedef struct {
   SilcClientResumeSessionCallback callback;
   void *context;
   SilcUInt32 channel_count;
+  SilcUInt32 *cmd_idents;
+  SilcUInt32 cmd_idents_count;
+  bool success;
 } *SilcClientResumeSession;
 
+/* Generic command reply callback. */
+
+SILC_CLIENT_CMD_REPLY_FUNC(resume)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SILC_LOG_DEBUG(("Start"));
+  SILC_CLIENT_PENDING_EXEC(cmd, silc_command_get(cmd->payload));
+}
+
+/* Special command reply callback for IDENTIFY callbacks.  This calls
+   the pending callback for every returned command entry. */
+
+SILC_CLIENT_CMD_REPLY_FUNC(resume_special)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  int i;
+
+  SILC_LOG_DEBUG(("Start"));
+  for (i = 0; i < cmd->callbacks_count; i++)
+    if (cmd->callbacks[i].callback)
+      (*cmd->callbacks[i].callback)(cmd->callbacks[i].context, cmd);
+}
+
+/* Completion calling callback */
+
+SILC_TASK_CALLBACK(silc_client_resume_call_completion)
+{
+  SilcClientResumeSession session = context;
+  int i;
+
+  SILC_LOG_DEBUG(("Session completed"));
+
+  for (i = 0; i < session->cmd_idents_count; i++)
+    silc_client_command_pending_del(session->conn, SILC_COMMAND_IDENTIFY, 
+                                   session->cmd_idents[i]);
+  silc_free(session->cmd_idents);
+
+  session->callback(session->client, session->conn, session->success,
+                   session->context);
+
+  memset(session, 'F', sizeof(*session));
+  silc_free(session);
+}
+
 /* This function is used to perform the resuming procedure after the
    client has connected to the server properly and has received the
    Client ID for the resumed session.  This resolves all channels
@@ -219,7 +264,7 @@ void silc_client_resume_session(SilcClient client,
 
   /* Second, send IDENTIFY command of all channels we know about.  These
      are the channels we've joined to according our detachment data. */
-  if (silc_idcache_get_all(conn->channel_cache, &list)) {
+  if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
     unsigned char **res_argv = NULL;
     SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0;
 
@@ -247,18 +292,25 @@ void silc_client_resume_session(SilcClient client,
       /* Send the IDENTIFY command */
       SILC_LOG_DEBUG(("Sending IDENTIFY"));
       silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
-                                  silc_client_command_reply_resume,
+                                  silc_client_command_reply_resume_special,
                                   0, ++conn->cmd_ident);
-      tmp = silc_command_payload_encode(SILC_COMMAND_IDENTIFY,
-                                       res_argc, res_argv, res_argv_lens,
-                                       res_argv_types, conn->cmd_ident);
       silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
                                  conn->cmd_ident,
                                  silc_client_command_resume_identify,
                                  session);
+
+      tmp = silc_command_payload_encode(SILC_COMMAND_IDENTIFY,
+                                       res_argc, res_argv, res_argv_lens,
+                                       res_argv_types, conn->cmd_ident);
       silc_client_packet_send(client, conn->sock, SILC_PACKET_COMMAND, 
                              NULL, 0, NULL, NULL, tmp->data, tmp->len, TRUE);
 
+      session->cmd_idents = silc_realloc(session->cmd_idents,
+                                        sizeof(*session->cmd_idents) *
+                                        (session->cmd_idents_count + 1));
+      session->cmd_idents[session->cmd_idents_count] = conn->cmd_ident;
+      session->cmd_idents_count++;
+
       for (i = 0; i < res_argc; i++)
        silc_free(res_argv[i]);
       silc_free(res_argv);
@@ -268,6 +320,9 @@ void silc_client_resume_session(SilcClient client,
     }
   }
 
+  if (!session->channel_count)
+    RESUME_CALL_COMPLETION(client, session, TRUE);
+
   /* Now, we wait for replies to come back and then continue with USERS,
      CMODE and TOPIC commands. */
 }
@@ -355,8 +410,7 @@ SILC_CLIENT_CMD_FUNC(resume_identify)
  err:
   session->channel_count--;
   if (!session->channel_count)
-    session->callback(session->client, session->conn, FALSE,
-                     session->context);
+    RESUME_CALL_COMPLETION(client, session, FALSE);
 }
 
 /* Received cmode to channel entry */
@@ -418,8 +472,7 @@ SILC_CLIENT_CMD_FUNC(resume_cmode)
  err:
   session->channel_count--;
   if (!session->channel_count)
-    session->callback(session->client, session->conn, FALSE,
-                     session->context);
+    RESUME_CALL_COMPLETION(client, session, FALSE);
 }
 
 /* Received users reply to a channel entry */
@@ -500,14 +553,13 @@ SILC_CLIENT_CMD_FUNC(resume_users)
   SILC_LOG_DEBUG(("Sending TOPIC"));
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
   silc_client_command_send(client, conn, SILC_COMMAND_TOPIC,
-                          conn->cmd_ident, 1, 1, tmp, tmp_len);
+                          ++conn->cmd_ident, 1, 1, tmp, tmp_len);
 
   /* Call the completion callback after we've got reply to all of
      our channels */
   session->channel_count--;
   if (!session->channel_count)
-    session->callback(session->client, session->conn, TRUE,
-                     session->context);
+    RESUME_CALL_COMPLETION(client, session, TRUE);
 
   silc_free(channel_id);
   return;
@@ -516,6 +568,5 @@ SILC_CLIENT_CMD_FUNC(resume_users)
   silc_free(channel_id);
   session->channel_count--;
   if (!session->channel_count)
-    session->callback(session->client, session->conn, FALSE,
-                     session->context);
+    RESUME_CALL_COMPLETION(client, session, FALSE);
 }