From: Pekka Riikonen Date: Sat, 22 Jun 2002 20:53:15 +0000 (+0000) Subject: Added support for handling notifys always in same order as X-Git-Tag: silc.client.0.9.3~3 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=d56ab2d482dd7f21ceb3b18a1f4fe833bc0a9c3f Added support for handling notifys always in same order as received from server, regardless if some notify causes some entry to be resolved. Subsequent notifys wait for completion of the resolving. --- diff --git a/lib/doc/building.html b/lib/doc/building.html index c0a7f64d..52ba44b7 100644 --- a/lib/doc/building.html +++ b/lib/doc/building.html @@ -68,6 +68,18 @@ library instead of using the MPI library included in the package, you can give the --with-gmp=PATH option to the `configure'. The PATH is the path to the GMP library in your system. +
 
+--without-irssi
+--without-silcd + +
 
+By default the SILC Toolkit will also build the Irssi SILC client and +the SILC Server which use the SILC Toolkit as well. If you do not +wish to compile these applications you can give --without-irssi to +not compile Irssi SILC client (irssi/ directory) and/or --without-silcd +to not compile SILC Server (silcd/ directory). Other applications +the Toolkit does not build automatically. +
 
--disable-asm diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index b459ee89..f44aefbd 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -239,9 +239,6 @@ void silc_client_del_connection(SilcClient client, SilcClientConnection conn) { int i; - SILC_LOG_DEBUG(("Deleting connection %s%d", conn->remote_host, - conn->remote_port)); - for (i = 0; i < client->internal->conns_count; i++) if (client->internal->conns[i] == conn) { diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index 49897691..a137ce47 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -82,6 +82,68 @@ static void silc_client_notify_by_server_pending(void *context, void *context2) silc_free(res); } +/* Resets the channel entry's resolve_cmd_ident after whatever-thing + was resolved is completed. */ + +static void silc_client_channel_cond(void *context, void *context2) +{ + SilcClientNotifyResolve res = (SilcClientNotifyResolve)context; + SilcClient client = res->context; + SilcClientConnection conn = res->sock->user_data; + SilcChannelID *channel_id = res->packet; + SilcChannelEntry channel; + channel = silc_client_get_channel_by_id(client, conn, channel_id); + if (channel) + channel->resolve_cmd_ident = 0; + silc_free(channel_id); + silc_socket_free(res->sock); + silc_free(res); +} + +/* Function that starts waiting for the `cmd_ident' to arrive and + marks the channel info being resolved. */ + +static void silc_client_channel_set_wait(SilcClient client, + SilcClientConnection conn, + SilcChannelEntry channel, + SilcUInt16 cmd_ident) +{ + SilcClientNotifyResolve res; + + if (!channel->resolve_cmd_ident) { + res = silc_calloc(1, sizeof(*res)); + res->context = client; + res->sock = silc_socket_dup(conn->sock); + res->packet = silc_id_dup(channel->id, SILC_ID_CHANNEL); + silc_client_command_pending(conn, SILC_COMMAND_NONE, cmd_ident, + silc_client_channel_cond, res); + channel->resolve_cmd_ident = cmd_ident; + } +} + +/* Attaches to the channel's resolving cmd ident and calls the + notify handling with `packet' after it's received. */ + +static void silc_client_channel_wait(SilcClient client, + SilcClientConnection conn, + SilcChannelEntry channel, + SilcPacketContext *packet) +{ + SilcClientNotifyResolve res; + + if (!channel->resolve_cmd_ident) + return; + + res = silc_calloc(1, sizeof(*res)); + res->packet = silc_packet_context_dup(packet); + res->context = client; + res->sock = silc_socket_dup(conn->sock); + + silc_client_command_pending(conn, SILC_COMMAND_NONE, + channel->resolve_cmd_ident, + silc_client_notify_by_server_pending, res); +} + /* Resolve client, channel or server information. */ static void silc_client_notify_by_server_resolve(SilcClient client, @@ -386,6 +448,15 @@ void silc_client_notify_by_server(SilcClient client, SILC_LOG_DEBUG(("Notify: TOPIC_SET")); + /* Get channel entry */ + channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len, + SILC_ID_CHANNEL); + if (!channel_id) + goto out; + channel = silc_client_get_channel_by_id(client, conn, channel_id); + if (!channel) + break; + /* Get ID */ tmp = silc_argument_get_arg_type(args, 1, &tmp_len); if (!tmp) @@ -400,6 +471,8 @@ void silc_client_notify_by_server(SilcClient client, client_id = id; client_entry = silc_client_get_client_by_id(client, conn, client_id); if (!client_entry) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_CLIENT, client_id); goto out; @@ -409,8 +482,28 @@ void silc_client_notify_by_server(SilcClient client, server_id = id; server = silc_client_get_server_by_id(client, conn, server_id); if (!server) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_SERVER, server_id); + server = silc_client_add_server(client, conn, NULL, NULL, server_id); + if (!server) + goto out; + + server->resolve_cmd_ident = conn->cmd_ident; + server_id = NULL; + goto out; + } + + /* If entry being resoled, wait for it before processing this notify */ + if (server->resolve_cmd_ident) { + SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res)); + res->packet = silc_packet_context_dup(packet); + res->context = client; + res->sock = silc_socket_dup(conn->sock); + silc_client_command_pending(conn, SILC_COMMAND_NONE, + server->resolve_cmd_ident, + silc_client_notify_by_server_pending, res); goto out; } @@ -418,18 +511,17 @@ void silc_client_notify_by_server(SilcClient client, client_entry = (SilcClientEntry)server; } else { /* Find Channel entry */ + silc_free(channel_id); channel_id = id; - channel = silc_client_get_channel_by_id(client, conn, channel_id); - if (!channel) { + client_entry = (SilcClientEntry) + silc_client_get_channel_by_id(client, conn, channel_id); + if (!client_entry) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_CHANNEL, channel_id); goto out; } - - /* Save the pointer to the client_entry pointer */ - client_entry = (SilcClientEntry)channel; - silc_free(channel_id); - channel_id = NULL; } /* Get topic */ @@ -437,14 +529,11 @@ void silc_client_notify_by_server(SilcClient client, if (!tmp) goto out; - /* Get channel entry */ - channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len, - SILC_ID_CHANNEL); - if (!channel_id) + /* If information is being resolved for this channel, wait for it */ + if (channel->resolve_cmd_ident) { + silc_client_channel_wait(client, conn, channel, packet); goto out; - channel = silc_client_get_channel_by_id(client, conn, channel_id); - if (!channel) - break; + } /* Notify application. The channel entry is sent last as this notify is for channel but application don't know it from the arguments @@ -593,6 +682,15 @@ void silc_client_notify_by_server(SilcClient client, SILC_LOG_DEBUG(("Notify: CMODE_CHANGE")); + /* Get channel entry */ + channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len, + SILC_ID_CHANNEL); + if (!channel_id) + goto out; + channel = silc_client_get_channel_by_id(client, conn, channel_id); + if (!channel) + goto out; + /* Get ID */ tmp = silc_argument_get_arg_type(args, 1, &tmp_len); if (!tmp) @@ -607,6 +705,8 @@ void silc_client_notify_by_server(SilcClient client, client_id = id; client_entry = silc_client_get_client_by_id(client, conn, client_id); if (!client_entry) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_CLIENT, client_id); goto out; @@ -616,27 +716,46 @@ void silc_client_notify_by_server(SilcClient client, server_id = id; server = silc_client_get_server_by_id(client, conn, server_id); if (!server) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_SERVER, server_id); + server = silc_client_add_server(client, conn, NULL, NULL, server_id); + if (!server) + goto out; + + server->resolve_cmd_ident = conn->cmd_ident; + server_id = NULL; goto out; } + /* If entry being resoled, wait for it before processing this notify */ + if (server->resolve_cmd_ident) { + SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res)); + res->packet = silc_packet_context_dup(packet); + res->context = client; + res->sock = silc_socket_dup(conn->sock); + silc_client_command_pending(conn, SILC_COMMAND_NONE, + server->resolve_cmd_ident, + silc_client_notify_by_server_pending, res); + goto out; + } + /* Save the pointer to the client_entry pointer */ client_entry = (SilcClientEntry)server; } else { /* Find Channel entry */ + silc_free(channel_id); channel_id = id; - channel = silc_client_get_channel_by_id(client, conn, channel_id); - if (!channel) { + client_entry = (SilcClientEntry) + silc_client_get_channel_by_id(client, conn, channel_id); + if (!client_entry) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_CHANNEL, channel_id); goto out; } - - /* Save the pointer to the client_entry pointer */ - client_entry = (SilcClientEntry)channel; - silc_free(channel_id); - channel_id = NULL; } /* Get the mode */ @@ -646,14 +765,11 @@ void silc_client_notify_by_server(SilcClient client, SILC_GET32_MSB(mode, tmp); - /* Get channel entry */ - channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len, - SILC_ID_CHANNEL); - if (!channel_id) - goto out; - channel = silc_client_get_channel_by_id(client, conn, channel_id); - if (!channel) + /* If information is being resolved for this channel, wait for it */ + if (channel->resolve_cmd_ident) { + silc_client_channel_wait(client, conn, channel, packet); goto out; + } /* Save the new mode */ channel->mode = mode; @@ -690,6 +806,15 @@ void silc_client_notify_by_server(SilcClient client, SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE")); + /* Get channel entry */ + channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len, + SILC_ID_CHANNEL); + if (!channel_id) + goto out; + channel = silc_client_get_channel_by_id(client, conn, channel_id); + if (!channel) + break; + /* Get ID */ tmp = silc_argument_get_arg_type(args, 1, &tmp_len); if (!tmp) @@ -704,6 +829,8 @@ void silc_client_notify_by_server(SilcClient client, client_id = id; client_entry = silc_client_get_client_by_id(client, conn, client_id); if (!client_entry) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_CLIENT, client_id); goto out; @@ -713,8 +840,28 @@ void silc_client_notify_by_server(SilcClient client, server_id = id; server = silc_client_get_server_by_id(client, conn, server_id); if (!server) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_SERVER, server_id); + server = silc_client_add_server(client, conn, NULL, NULL, server_id); + if (!server) + goto out; + + server->resolve_cmd_ident = conn->cmd_ident; + server_id = NULL; + goto out; + } + + /* If entry being resoled, wait for it before processing this notify */ + if (server->resolve_cmd_ident) { + SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res)); + res->packet = silc_packet_context_dup(packet); + res->context = client; + res->sock = silc_socket_dup(conn->sock); + silc_client_command_pending(conn, SILC_COMMAND_NONE, + server->resolve_cmd_ident, + silc_client_notify_by_server_pending, res); goto out; } @@ -722,18 +869,17 @@ void silc_client_notify_by_server(SilcClient client, client_entry = (SilcClientEntry)server; } else { /* Find Channel entry */ + silc_free(channel_id); channel_id = id; - channel = silc_client_get_channel_by_id(client, conn, channel_id); - if (!channel) { + client_entry = (SilcClientEntry) + silc_client_get_channel_by_id(client, conn, channel_id); + if (!client_entry) { + silc_client_channel_set_wait(client, conn, channel, + conn->cmd_ident + 1); silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_CHANNEL, channel_id); goto out; } - - /* Save the pointer to the client_entry pointer */ - client_entry = (SilcClientEntry)channel; - silc_free(channel_id); - channel_id = NULL; } /* Get the mode */ @@ -743,6 +889,12 @@ void silc_client_notify_by_server(SilcClient client, SILC_GET32_MSB(mode, tmp); + /* If information is being resolved for this channel, wait for it */ + if (channel->resolve_cmd_ident) { + silc_client_channel_wait(client, conn, channel, packet); + goto out; + } + /* Get target Client ID */ tmp = silc_argument_get_arg_type(args, 3, &tmp_len); if (!tmp) @@ -762,15 +914,6 @@ void silc_client_notify_by_server(SilcClient client, goto out; } - /* Get channel entry */ - channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len, - SILC_ID_CHANNEL); - if (!channel_id) - goto out; - channel = silc_client_get_channel_by_id(client, conn, channel_id); - if (!channel) - break; - /* Save the mode */ chu = silc_client_on_channel(channel, client_entry2); if (chu) @@ -978,6 +1121,25 @@ void silc_client_notify_by_server(SilcClient client, if (!server) { silc_client_notify_by_server_resolve(client, conn, packet, SILC_ID_SERVER, server_id); + server = silc_client_add_server(client, conn, NULL, NULL, + server_id); + if (!server) + goto out; + + server->resolve_cmd_ident = conn->cmd_ident; + server_id = NULL; + goto out; + } + + if (server->resolve_cmd_ident) { + SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res)); + res->packet = silc_packet_context_dup(packet); + res->context = client; + res->sock = silc_socket_dup(conn->sock); + silc_client_command_pending(conn, SILC_COMMAND_NONE, + server->resolve_cmd_ident, + silc_client_notify_by_server_pending, + res); goto out; } diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 1e2a21ff..46832f7e 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -432,8 +432,12 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, COMMAND_REPLY_ERROR; return; } + } else { + silc_client_update_server(client, conn, server_entry, name, info); } + server_entry->resolve_cmd_ident = 0; + /* Notify application */ if (notify) COMMAND_REPLY((ARGS, server_entry, name, info)); diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index 75bbc521..f20efc26 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -976,6 +976,8 @@ SilcServerEntry silc_client_add_server(SilcClient client, { SilcServerEntry server_entry; + SILC_LOG_DEBUG(("Start")); + server_entry = silc_calloc(1, sizeof(*server_entry)); if (!server_entry || !server_id) return NULL; @@ -1012,6 +1014,34 @@ bool silc_client_del_server(SilcClient client, SilcClientConnection conn, return ret; } +/* Updates the `server_entry' with the new information sent as argument. */ + +void silc_client_update_server(SilcClient client, + SilcClientConnection conn, + SilcServerEntry server_entry, + const char *server_name, + const char *server_info) +{ + SILC_LOG_DEBUG(("Start")); + + if (server_name && (!server_entry->server_name || + strcmp(server_entry->server_name, server_name))) { + + silc_idcache_del_by_context(conn->server_cache, server_entry); + silc_free(server_entry->server_name); + server_entry->server_name = strdup(server_name); + silc_idcache_add(conn->server_cache, server_entry->server_name, + server_entry->server_id, + server_entry, 0, NULL); + } + + if (server_info && (!server_entry->server_info || + strcmp(server_entry->server_info, server_info))) { + silc_free(server_entry->server_info); + server_entry->server_info = strdup(server_info); + } +} + /* Formats the nickname of the client specified by the `client_entry'. If the format is specified by the application this will format the nickname and replace the old nickname in the client entry. If the diff --git a/lib/silcclient/idlist.h b/lib/silcclient/idlist.h index 3e7eb253..7d9a89ec 100644 --- a/lib/silcclient/idlist.h +++ b/lib/silcclient/idlist.h @@ -24,7 +24,7 @@ typedef enum { SILC_CLIENT_STATUS_NONE = 0x0000, SILC_CLIENT_STATUS_RESOLVING = 0x0001, -} SilcClientStatus; +} SilcEntryStatus; /* Client entry context. When client receives information about new client (it receives its ID, for example, by IDENTIFY request) we create new @@ -43,7 +43,7 @@ struct SilcClientEntryStruct { SilcCipher send_key; /* Private message key for sending */ SilcCipher receive_key; /* Private message key for receiving */ SilcClientKeyAgreement ke; /* Current key agreement context or NULL */ - SilcClientStatus status; /* Status mask */ + SilcEntryStatus 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 @@ -67,6 +67,7 @@ struct SilcChannelEntryStruct { char *channel_name; SilcChannelID *id; SilcUInt32 mode; + SilcUInt16 resolve_cmd_ident; /* All clients that has joined this channel */ SilcHashTable user_list; @@ -74,7 +75,7 @@ struct SilcChannelEntryStruct { /* Channel keys */ SilcCipher channel_key; /* The channel key */ unsigned char *key; /* Raw key data */ - SilcUInt32 key_len; + SilcUInt32 key_len; /* Raw key data length */ unsigned char iv[SILC_CIPHER_MAX_IV_SIZE]; /* Current IV */ SilcHmac hmac; /* Current HMAC */ SilcDList private_keys; /* List of private keys or NULL */ @@ -95,6 +96,7 @@ struct SilcServerEntryStruct { char *server_name; char *server_info; SilcServerID *server_id; + SilcUInt16 resolve_cmd_ident; }; /* Prototypes. These are used only by the library. Application should not @@ -129,6 +131,11 @@ SilcServerEntry silc_client_add_server(SilcClient client, const char *server_name, const char *server_info, SilcServerID *server_id); +void silc_client_update_server(SilcClient client, + SilcClientConnection conn, + SilcServerEntry server_entry, + const char *server_name, + const char *server_info); bool silc_client_replace_channel_id(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel,