X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient_resume.c;h=5b984234c7f4fe48bfe60bbaf595612ce57765a9;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=b0e08ed65031d5ea97cafa7a64ca86e49c7f356a;hpb=57fe1d5d88e8687ac876aa3725028bd3343f5067;p=silc.git diff --git a/lib/silcclient/client_resume.c b/lib/silcclient/client_resume.c index b0e08ed6..5b984234 100644 --- a/lib/silcclient/client_resume.c +++ b/lib/silcclient/client_resume.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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 @@ -18,7 +18,7 @@ */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.h" #include "silcclient.h" #include "client_internal.h" @@ -29,6 +29,7 @@ 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, \ @@ -66,7 +67,7 @@ SilcBuffer silc_client_get_detach_data(SilcClient client, /* 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); @@ -98,10 +99,10 @@ SilcBuffer silc_client_get_detach_data(SilcClient client, /* 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, +SilcBool silc_client_process_detach_data(SilcClient client, SilcClientConnection conn, unsigned char **old_id, SilcUInt16 *old_id_len) @@ -109,18 +110,21 @@ 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), @@ -128,6 +132,11 @@ bool silc_client_process_detach_data(SilcClient client, 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); @@ -173,19 +182,32 @@ typedef struct { SilcClientResumeSessionCallback callback; void *context; SilcUInt32 channel_count; - bool success; + SilcUInt32 *cmd_idents; + SilcUInt32 cmd_idents_count; + SilcBool 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 */ @@ -193,8 +215,20 @@ SILC_CLIENT_CMD_REPLY_FUNC(resume) 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 @@ -215,7 +249,7 @@ void silc_client_resume_session(SilcClient client, SilcChannelEntry channel; SilcBuffer tmp; int i; - bool ret; + SilcBool ret; SILC_LOG_DEBUG(("Resuming detached session")); @@ -238,7 +272,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; @@ -266,18 +300,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, + 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); @@ -287,6 +328,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. */ } @@ -366,7 +410,7 @@ SILC_CLIENT_CMD_FUNC(resume_identify) 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; @@ -393,7 +437,7 @@ SILC_CLIENT_CMD_FUNC(resume_cmode) 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); @@ -456,7 +500,7 @@ SILC_CLIENT_CMD_FUNC(resume_users) 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); @@ -466,19 +510,19 @@ SILC_CLIENT_CMD_FUNC(resume_users) /* 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); @@ -486,7 +530,7 @@ SILC_CLIENT_CMD_FUNC(resume_users) /* 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); @@ -494,7 +538,7 @@ SILC_CLIENT_CMD_FUNC(resume_users) /* 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); @@ -508,8 +552,8 @@ SILC_CLIENT_CMD_FUNC(resume_users) 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); @@ -517,7 +561,7 @@ 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 */