Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 Pekka Riikonen
+ Copyright (C) 2002, 2004 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#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, \
/* Save all joined channels */
silc_hash_table_list(conn->local_entry->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+ while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
unsigned char *chid = silc_id_id2str(chu->channel->id, SILC_ID_CHANNEL);
SilcUInt16 chid_len = silc_id_get_len(chu->channel->id, SILC_ID_CHANNEL);
/* Processes the detachment data. This creates channels and other
stuff according the data found in the the connection parameters.
This doesn't actually resolve any detailed information from the
- server. To do that call silc_client_resume_session function.
+ server. To do that call silc_client_resume_session function.
This returns the old detached session client ID. */
bool silc_client_process_detach_data(SilcClient client,
SilcBufferStruct detach;
SilcUInt32 ch_count;
int i, len;
+ char *newnick;
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);
+ *old_id = NULL;
+ *old_id_len = 0;
+
/* Take the old client ID from the detachment data */
len = silc_buffer_unformat(&detach,
- SILC_STR_UI16_NSTRING_ALLOC(&conn->nickname,
+ SILC_STR_UI16_NSTRING_ALLOC(&newnick,
NULL),
SILC_STR_UI16_NSTRING_ALLOC(old_id, old_id_len),
SILC_STR_UI_INT(NULL),
SILC_STR_END);
if (len == -1)
return FALSE;
+ if (!newnick || !(*old_id) || !(*old_id_len))
+ return FALSE;
+
+ silc_free(conn->nickname);
+ conn->nickname = newnick;
silc_buffer_pull(&detach, len);
SilcClientResumeSessionCallback callback;
void *context;
SilcUInt32 channel_count;
+ SilcUInt32 *cmd_idents;
+ SilcUInt32 cmd_idents_count;
bool success;
} *SilcClientResumeSession;
-/* Generic command reply callback */
+/* 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. */
- if (cmd->callback)
- (*cmd->callback)(cmd->context, cmd);
+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
/* 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,
+ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
conn->cmd_ident,
silc_client_command_resume_identify,
session);
- silc_client_packet_send(client, conn->sock, SILC_PACKET_COMMAND,
+
+ 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. */
}
return;
/* Unregister this command reply */
- silc_client_command_unregister(client, SILC_COMMAND_IDENTIFY, NULL,
+ silc_client_command_unregister(client, SILC_COMMAND_IDENTIFY, NULL,
silc_client_command_reply_resume,
cmd->ident);
return;
SILC_LOG_DEBUG(("Start"));
/* Unregister this command reply */
- silc_client_command_unregister(client, SILC_COMMAND_CMODE, NULL,
+ silc_client_command_unregister(client, SILC_COMMAND_CMODE, NULL,
silc_client_command_reply_resume,
cmd->ident);
SILC_LOG_DEBUG(("Start"));
/* Unregister this command reply */
- silc_client_command_unregister(client, SILC_COMMAND_USERS, NULL,
+ silc_client_command_unregister(client, SILC_COMMAND_USERS, NULL,
silc_client_command_reply_users_i,
cmd->ident);
/* Get channel ID */
tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
if (!tmp) {
- COMMAND_REPLY_ERROR;
+ COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto err;
}
channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!channel_id) {
- COMMAND_REPLY_ERROR;
+ COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto err;
}
/* Get the list count */
tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
if (!tmp) {
- COMMAND_REPLY_ERROR;
+ COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto err;
}
SILC_GET32_MSB(list_count, tmp);
/* Get Client ID list */
tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
if (!tmp) {
- COMMAND_REPLY_ERROR;
+ COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto err;
}
silc_buffer_set(&client_id_list, tmp, tmp_len);
/* Get client mode list */
tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
if (!tmp) {
- COMMAND_REPLY_ERROR;
+ COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto err;
}
silc_buffer_set(&client_mode_list, tmp, tmp_len);
client->internal->ops->command_reply(client, conn, cmd->payload, TRUE,
SILC_COMMAND_JOIN, cmd->status,
channel->channel_name, channel,
- channel->mode, 0,
- NULL, NULL, NULL, NULL,
+ channel->mode, 0,
+ NULL, NULL, NULL, NULL,
channel->hmac, list_count,
&client_id_list, client_mode_list);
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 */