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. */
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);
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 {
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
/* 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;
/* 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);
}
}
+ 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. */
}
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 */
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 */
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;
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);
}