From 31b9c6e9ceffe13a84659d337e35f7a5960ac6d9 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Fri, 12 Apr 2002 18:24:46 +0000 Subject: [PATCH] updates. --- CHANGES | 10 +++++ apps/irssi/src/silc/core/client_ops.c | 5 ++- apps/irssi/src/silc/core/silc-servers.c | 7 ++++ apps/silcd/packet_receive.c | 8 +++- lib/silcclient/client_notify.c | 3 +- lib/silcclient/client_prvmsg.c | 1 + lib/silcclient/client_resume.c | 48 +++++++++++++++++++----- lib/silcclient/command.c | 50 +++++++++++++++++-------- lib/silcclient/command.h | 24 ++++++------ lib/silcclient/command_reply.c | 24 +++++++++--- lib/silcclient/command_reply.h | 10 ++++- lib/silcclient/idlist.c | 20 +++++++--- lib/silcclient/idlist.h | 13 ++++--- 13 files changed, 167 insertions(+), 56 deletions(-) diff --git a/CHANGES b/CHANGES index dcb48950..089a3c93 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,13 @@ +Fri Apr 12 20:09:08 EEST 2002 Pekka Riikonen + + Added resolve_cmd_ident field to the SilcClientEntry structure + too so that if the entry is for example being resolved so + another command may attach to the same pending command reply + without requiring to resolve the same entry again. Added + support for adding multiple pending commands for one + command idenfier. Affected files lib/silcclient/command.[ch], + lib/silcclient/command_reply.[ch], lib/silcclient/idlist.h. + Fri Apr 12 10:17:51 EEST 2002 Pekka Riikonen * Defined that server receives WHOIS command reply for private diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 6bbf81a5..5a5ee7b5 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -633,7 +633,7 @@ void silc_connect(SilcClient client, SilcClientConnection conn, { SILC_SERVER_REC *server = conn->context; - if (!server || status == SILC_CLIENT_CONN_ERROR) { + if (!server) { silc_client_close_connection(client, conn); return; } @@ -749,6 +749,9 @@ static void silc_client_join_get_users(SilcClient client, SilcClientEntry founder = NULL; NICK_REC *ownnick; + SILC_LOG_DEBUG(("Start, channel %s, %d users", channel->channel_name, + silc_hash_table_count(channel->user_list))); + if (!clients) return; diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index 841b8411..835e20bc 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -41,6 +41,8 @@ #include "window-item-def.h" #include "fe-common/core/printtext.h" +#include "fe-common/core/fe-channels.h" +#include "fe-common/core/keyboard.h" #include "fe-common/silc/module-formats.h" #include "silc-commands.h" @@ -214,6 +216,11 @@ static void sig_connected(SILC_SERVER_REC *server) server); server->conn = conn; + if (params.detach_data) + keyboard_entry_redirect(NULL, + "-- Resuming old session, may take a while ...", + ENTRY_REDIRECT_FLAG_HIDDEN, server); + silc_free(params.detach_data); unlink(file); diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 42085c6f..afdc1a62 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -3059,7 +3059,8 @@ void silc_server_resume_client(SilcServer server, /* As router we must deliver this packet directly to the original server whom this client was earlier. */ - if (server->server_type == SILC_ROUTER && detached_client->router) + if (server->server_type == SILC_ROUTER && detached_client->router && + detached_client->router->server_type != SILC_ROUTER) silc_server_packet_send(server, detached_client->router->connection, SILC_PACKET_RESUME_CLIENT, 0, buf->data, buf->len, TRUE); @@ -3253,6 +3254,11 @@ void silc_server_resume_client(SilcServer server, } } + if (server->server_type == SILC_ROUTER && + sock->type == SILC_SOCKET_TYPE_ROUTER && + server_entry->server_type == SILC_ROUTER) + local = FALSE; + SILC_LOG_DEBUG(("Resuming detached client")); /* Change the client to correct list. */ diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index 7a48419f..c1303069 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -223,9 +223,10 @@ void silc_client_notify_by_server(SilcClient client, client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; goto out; } - client_entry->status |= SILC_CLIENT_STATUS_RESOLVING; silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_CLIENT, client_id); + client_entry->status |= SILC_CLIENT_STATUS_RESOLVING; + client_entry->resolve_cmd_ident = conn->cmd_ident; goto out; } else { if (client_entry != conn->local_entry) diff --git a/lib/silcclient/client_prvmsg.c b/lib/silcclient/client_prvmsg.c index a6e09917..439fe0e3 100644 --- a/lib/silcclient/client_prvmsg.c +++ b/lib/silcclient/client_prvmsg.c @@ -168,6 +168,7 @@ void silc_client_private_message(SilcClient client, goto out; } remote_client->status |= SILC_CLIENT_STATUS_RESOLVING; + remote_client->resolve_cmd_ident = conn->cmd_ident + 1; } /* Resolve the client info */ diff --git a/lib/silcclient/client_resume.c b/lib/silcclient/client_resume.c index b0e08ed6..d3fd7a9d 100644 --- a/lib/silcclient/client_resume.c +++ b/lib/silcclient/client_resume.c @@ -173,19 +173,32 @@ typedef struct { 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. */ + +SILC_CLIENT_CMD_REPLY_FUNC(resume_special) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + int i; - if (cmd->callback) - (*cmd->callback)(cmd->context, cmd); + 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 +206,18 @@ SILC_CLIENT_CMD_REPLY_FUNC(resume) SILC_TASK_CALLBACK(silc_client_resume_call_completion) { SilcClientResumeSession session = context; + int i; + session->callback(session->client, session->conn, session->success, session->context); + + 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); + + memset(session, 'F', sizeof(*session)); + silc_free(session); } /* This function is used to perform the resuming procedure after the @@ -266,18 +289,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); @@ -517,7 +547,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 */ diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index f04e4510..1e829efa 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -86,10 +86,13 @@ void silc_client_command_call(SilcClientCommand command, } /* Add new pending command to be executed when reply to a command has been - received. The `reply_cmd' is the command that will call the `callback' - with `context' when reply has been received. If `ident is non-zero - the `callback' will be executed when received reply with command - identifier `ident'. */ + received. The `reply_cmd' is the command that will call the `callback' + with `context' when reply has been received. It can be SILC_COMMAND_NONE + to match any command with the `ident'. If `ident' is non-zero + the `callback' will be executed when received reply with command + identifier `ident'. If there already exists pending command for the + specified command, ident, callback and context this function has no + effect. */ void silc_client_command_pending(SilcClientConnection conn, SilcCommand reply_cmd, @@ -99,6 +102,16 @@ void silc_client_command_pending(SilcClientConnection conn, { SilcClientCommandPending *reply; + /* Check whether identical pending already exists for same command, + ident, callback and callback context. If it does then it would be + error to register it again. */ + silc_dlist_start(conn->pending_commands); + while ((reply = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) { + if (reply->reply_cmd == reply_cmd && reply->ident == ident && + reply->callback == callback && reply->context == context) + return; + } + reply = silc_calloc(1, sizeof(*reply)); reply->reply_cmd = reply_cmd; reply->ident = ident; @@ -125,26 +138,33 @@ void silc_client_command_pending_del(SilcClientConnection conn, } /* Checks for pending commands and marks callbacks to be called from - the command reply function. Returns TRUE if there were pending command. */ - -int silc_client_command_pending_check(SilcClientConnection conn, - SilcClientCommandReplyContext ctx, - SilcCommand command, - SilcUInt16 ident) + the command reply function. */ + +SilcClientCommandPendingCallbacks +silc_client_command_pending_check(SilcClientConnection conn, + SilcClientCommandReplyContext ctx, + SilcCommand command, + SilcUInt16 ident, + SilcUInt32 *callbacks_count) { SilcClientCommandPending *r; + SilcClientCommandPendingCallbacks callbacks = NULL; + int i = 0; silc_dlist_start(conn->pending_commands); while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) { - if (r->reply_cmd == command && r->ident == ident) { - ctx->context = r->context; - ctx->callback = r->callback; + if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE) + && r->ident == ident) { + callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1)); + callbacks[i].context = r->context; + callbacks[i].callback = r->callback; ctx->ident = ident; - return TRUE; + i++; } } - return FALSE; + *callbacks_count = i; + return callbacks; } /* Allocate Command Context */ diff --git a/lib/silcclient/command.h b/lib/silcclient/command.h index 33479ec8..46fb3650 100644 --- a/lib/silcclient/command.h +++ b/lib/silcclient/command.h @@ -87,12 +87,13 @@ silc_client_command_unregister(client, SILC_COMMAND_##cmd, \ void silc_client_command_##func(void *context, void *context2) /* Executed pending command callback */ -#define SILC_CLIENT_PENDING_EXEC(ctx, cmd) \ -do { \ - if ((ctx)->callback) \ - (*ctx->callback)(ctx->context, ctx); \ - silc_client_command_pending_del((ctx)->sock->user_data, (cmd), \ - (ctx)->ident); \ +#define SILC_CLIENT_PENDING_EXEC(ctx, cmd) \ +do { \ + int _i; \ + for (_i = 0; _i < ctx->callbacks_count; _i++) \ + if (ctx->callbacks[_i].callback) \ + (*ctx->callbacks[_i].callback)(ctx->callbacks[_i].context, ctx); \ + silc_client_command_pending_del(ctx->sock->user_data, cmd, ctx->ident); \ } while(0) bool silc_client_command_register(SilcClient client, @@ -112,11 +113,12 @@ void silc_client_commands_unregister(SilcClient client); void silc_client_command_pending_del(SilcClientConnection conn, SilcCommand reply_cmd, SilcUInt16 ident); -int silc_client_command_pending_check(SilcClientConnection conn, - SilcClientCommandReplyContext ctx, - SilcCommand command, - SilcUInt16 ident); - +SilcClientCommandPendingCallbacks +silc_client_command_pending_check(SilcClientConnection conn, + SilcClientCommandReplyContext ctx, + SilcCommand command, + SilcUInt16 ident, + SilcUInt32 *callbacks_count); SILC_CLIENT_CMD_FUNC(whois); SILC_CLIENT_CMD_FUNC(whowas); SILC_CLIENT_CMD_FUNC(identify); diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 415f6d49..424d3ea2 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -127,9 +127,10 @@ void silc_client_command_reply_process(SilcClient client, silc_command_get_status(ctx->payload, &ctx->status, &ctx->error); /* Check for pending commands and mark to be exeucted */ - silc_client_command_pending_check(sock->user_data, ctx, - silc_command_get(ctx->payload), - ctx->ident); + ctx->callbacks = + silc_client_command_pending_check(sock->user_data, ctx, + silc_command_get(ctx->payload), + ctx->ident, &ctx->callbacks_count); /* Execute command reply */ @@ -267,7 +268,7 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; /* Notify application */ - if (!cmd->callback && notify) + if (!cmd->callbacks_count && notify) COMMAND_REPLY((ARGS, client_entry, nickname, username, realname, has_channels ? &channels : NULL, mode, idle, fingerprint, has_user_modes ? &ch_user_modes : NULL)); @@ -1527,6 +1528,7 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, int i; unsigned char **res_argv = NULL; SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0; + bool wait_res = FALSE; SILC_LOG_DEBUG(("Start")); @@ -1576,6 +1578,8 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, return 1; } + SILC_LOG_DEBUG(("channel %s, %d users", channel->channel_name, list_count)); + /* Cache the received Client ID's and modes. */ for (i = 0; i < list_count; i++) { SilcUInt16 idp_len; @@ -1597,11 +1601,18 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, if (!client_entry || !client_entry->username || !client_entry->realname) { if (client_entry) { if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) { + /* Attach to this resolving and wait until it finishes */ + silc_client_command_pending(conn, SILC_COMMAND_NONE, + client_entry->resolve_cmd_ident, + get_clients, cmd); + wait_res = TRUE; + silc_buffer_pull(&client_id_list, idp_len); silc_buffer_pull(&client_mode_list, 4); continue; } client_entry->status |= SILC_CLIENT_STATUS_RESOLVING; + client_entry->resolve_cmd_ident = conn->cmd_ident + 1; } /* No we don't have it (or it is incomplete in information), query @@ -1662,7 +1673,10 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd, silc_free(res_argv_types); return 1; } - + + if (wait_res) + return 1; + silc_buffer_push(&client_id_list, (client_id_list.data - client_id_list.head)); silc_buffer_push(&client_mode_list, (client_mode_list.data - diff --git a/lib/silcclient/command_reply.h b/lib/silcclient/command_reply.h index 782b0aa2..f950447d 100644 --- a/lib/silcclient/command_reply.h +++ b/lib/silcclient/command_reply.h @@ -26,6 +26,12 @@ typedef struct { SilcCommand cmd; } SilcClientCommandReply; +/* Context holding pending command callbacks. */ +typedef struct { + SilcCommandCb callback; + void *context; +} *SilcClientCommandPendingCallbacks; + /* Context sent as argument to all command reply functions */ struct SilcClientCommandReplyContextStruct { SilcClient client; @@ -37,8 +43,8 @@ struct SilcClientCommandReplyContextStruct { SilcPacketContext *packet; /* If defined this executes the pending command. */ - SilcCommandCb callback; - void *context; + SilcClientCommandPendingCallbacks callbacks; + SilcUInt32 callbacks_count; SilcUInt16 ident; }; diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index 9f21b8a5..2d5a8c0c 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -362,6 +362,7 @@ void silc_client_get_clients_by_list(SilcClient client, unsigned char **res_argv = NULL; SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0; GetClientsByListInternal in; + bool wait_res = FALSE; SILC_LOG_DEBUG(("Start")); @@ -402,13 +403,21 @@ void silc_client_get_clients_by_list(SilcClient client, if (entry) { if (entry->status & SILC_CLIENT_STATUS_RESOLVING) { - entry->status &= ~SILC_CLIENT_STATUS_RESOLVING; + /* Attach to this resolving and wait until it finishes */ + silc_client_command_pending( + conn, SILC_COMMAND_NONE, + entry->resolve_cmd_ident, + silc_client_command_get_clients_list_callback, + (void *)in); + wait_res = TRUE; + silc_free(client_id); silc_buffer_pull(client_id_list, idp_len); continue; } entry->status |= SILC_CLIENT_STATUS_RESOLVING; + entry->resolve_cmd_ident = conn->cmd_ident + 1; } /* No we don't have it, query it from the server. Assemble argument @@ -429,6 +438,9 @@ void silc_client_get_clients_by_list(SilcClient client, silc_buffer_pull(client_id_list, idp_len); } + silc_buffer_push(client_id_list, client_id_list->data - + client_id_list->head); + /* Query the client information from server if the list included clients that we don't know about. */ if (res_argc) { @@ -452,8 +464,6 @@ void silc_client_get_clients_by_list(SilcClient client, silc_client_command_get_clients_list_callback, (void *)in); - silc_buffer_push(client_id_list, client_id_list->data - - client_id_list->head); silc_buffer_free(res_cmd); silc_free(res_argv); silc_free(res_argv_lens); @@ -461,8 +471,8 @@ void silc_client_get_clients_by_list(SilcClient client, return; } - silc_buffer_push(client_id_list, client_id_list->data - - client_id_list->head); + if (wait_res) + return; /* We have the clients in cache, get them and call the completion */ silc_client_command_get_clients_list_callback((void *)in, NULL); diff --git a/lib/silcclient/idlist.h b/lib/silcclient/idlist.h index 39b4f022..3e7eb253 100644 --- a/lib/silcclient/idlist.h +++ b/lib/silcclient/idlist.h @@ -40,17 +40,18 @@ struct SilcClientEntryStruct { SilcClientID *id; /* The Client ID */ unsigned char *fingerprint; /* Fingerprint of client's public key */ SilcUInt32 fingerprint_len; /* Length of the fingerprint */ - bool valid; /* FALSE if this entry is not valid */ SilcCipher send_key; /* Private message key for sending */ SilcCipher receive_key; /* Private message key for receiving */ - unsigned char *key; /* Set only if appliation provided the - key material. NULL if the library - generated the key. */ - SilcUInt32 key_len; - bool generated; /* TRUE if library generated the key */ SilcClientKeyAgreement ke; /* Current key agreement context or NULL */ SilcClientStatus status; /* Status mask */ SilcHashTable channels; /* All channels client has joined */ + unsigned char *key; /* Set only if appliation provided the + key material. NULL if the library + generated the key. */ + SilcUInt32 key_len; /* Key length */ + SilcUInt16 resolve_cmd_ident; /* Command identifier when resolving */ + bool generated; /* TRUE if library generated `key' */ + bool valid; /* FALSE if this entry is not valid */ }; /* Client and its mode on a channel */ -- 2.24.0