From f6c51093b112f54d37bbffa627b5a6209f228b01 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 2 Nov 2000 22:15:23 +0000 Subject: [PATCH] Some bugfixes. Changed server->sim to SilcDList and code accordingly. Changes SilcClientEntry->channel to SilcList and added back-pointer to SilcChannelClientEntry which is now used by both client entry and channel entry --- apps/silcd/command.c | 25 ++--- apps/silcd/idlist.c | 4 +- apps/silcd/idlist.h | 63 +++++++----- apps/silcd/server.c | 179 ++++++++++++++++------------------- apps/silcd/server_internal.h | 5 +- apps/silcd/serverconfig.c | 21 ++-- 6 files changed, 142 insertions(+), 155 deletions(-) diff --git a/apps/silcd/command.c b/apps/silcd/command.c index dbad3bf3..04901d7e 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -486,9 +486,10 @@ SILC_SERVER_CMD_FUNC(whois) silc_buffer_free(packet); silc_buffer_free(idp); - silc_free(clients); } + silc_free(clients); + if (client_id) silc_free(client_id); @@ -1387,27 +1388,15 @@ SILC_SERVER_CMD_FUNC(join) goto out; } - /* Join the client to the channel by adding it to channel's user list */ + /* Join the client to the channel by adding it to channel's user list. + Add also the channel to client entry's channels list for fast cross- + referencing. */ chl = silc_calloc(1, sizeof(*chl)); chl->mode = umode; chl->client = client; + chl->channel = channel; silc_list_add(channel->user_list, chl); - - /* Add the channel to client's channel list */ - i = client->channel_count; - for (k = 0; k < client->channel_count; k++) { - if (client->channel[k] == NULL) { - client->channel[k] = channel; - break; - } - } - if (k >= i) { - i = client->channel_count; - client->channel = silc_realloc(client->channel, - sizeof(*client->channel) * (i + 1)); - client->channel[i] = channel; - client->channel_count++; - } + silc_list_add(client->channels, chl); /* Notify router about new user on channel. If we are normal server we send it to our router, if we are router we send it to our diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index 358bef33..0699c680 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -148,6 +148,8 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, client->hmac = hmac; client->public_key = public_key; client->connection = connection; + silc_list_init(client->channels, struct SilcChannelClientEntryStruct, + client_list); if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT, (void *)client->id, (void *)client, TRUE)) { @@ -378,7 +380,7 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, channel->router = router; channel->channel_key = channel_key; silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct, - next); + channel_list); if (!silc_idcache_add(id_list->channels, channel->channel_name, SILC_ID_CHANNEL, (void *)channel->id, diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index aa444f46..51a143bb 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -109,6 +109,44 @@ struct SilcServerEntryStruct { void *connection; }; +/* + SILC Channel Client entry structure. + + This entry used only by the SilcChannelEntry object and it holds + information about current clients (ie. users) on channel. Following + short description of the fields: + + SilcClientEntry client + + Pointer to the client list. This is the client currently on channel. + + unsigned int mode + + Client's current mode on the channel. + + SilcChannelEntry channel + + Back pointer back to channel. As this structure is also used by + SilcClientEntry we have this here for fast access to the channel when + used by SilcClientEntry. + + struct SilcChannelClientEntryStruct *client_list + struct SilcChannelClientEntryStruct *channel_list + + List member pointers. This structure is used by channel entry and + client entry thus we must have separate list member pointers for + them since we are using same entry for both lists (the entry is not + duplicated). SilcList requires this. + +*/ +typedef struct SilcChannelClientEntryStruct { + SilcClientEntry client; + unsigned int mode; + SilcChannelEntry channel; + struct SilcChannelClientEntryStruct *client_list; + struct SilcChannelClientEntryStruct *channel_list; +} *SilcChannelClientEntry; + /* SILC Client entry object. @@ -233,8 +271,7 @@ struct SilcClientEntryStruct { SilcServerEntry router; /* List of channels client has joined to */ - SilcChannelEntry *channel; - unsigned int channel_count; + SilcList channels; /* Keys */ SilcCipher send_key; @@ -247,28 +284,6 @@ struct SilcClientEntryStruct { void *connection; }; -/* - SILC Channel Client entry structure. - - This entry used only by the SilcChannelEntry object and it holds - information about current clients (ie. users) on channel. Following - short description of the fields: - - SilcClientEntry client - - Pointer to the client list. This is the client currently on channel. - - unsigned int mode - - Client's current mode on the channel. - -*/ -typedef struct SilcChannelClientEntryStruct { - SilcClientEntry client; - unsigned int mode; - struct SilcChannelClientEntryStruct *next; -} *SilcChannelClientEntry; - /* SILC Channel entry object. diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 3611f429..149b34b9 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -56,6 +56,9 @@ int silc_server_alloc(SilcServer *new_server) server->standalone = FALSE; server->local_list = silc_calloc(1, sizeof(*server->local_list)); server->global_list = silc_calloc(1, sizeof(*server->global_list)); +#ifdef SILC_SIM + server->sim = silc_dlist_init(); +#endif *new_server = server; @@ -68,6 +71,8 @@ int silc_server_alloc(SilcServer *new_server) void silc_server_free(SilcServer server) { if (server) { + SilcSimContext *sim; + if (server->local_list) silc_free(server->local_list); if (server->global_list) @@ -75,6 +80,12 @@ void silc_server_free(SilcServer server) if (server->rng) silc_rng_free(server->rng); + while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) { + silc_dlist_del(server->sim, sim); + silc_sim_free(sim); + } + silc_dlist_uninit(server->sim); + silc_math_primegen_uninit(); /* XXX */ silc_free(server); } @@ -1786,7 +1797,6 @@ void silc_server_packet_send_to_channel(SilcServer server, unsigned int data_len, int force_send) { - int i; SilcSocketConnection sock = NULL; SilcPacketContext packetdata; SilcClientEntry client = NULL; @@ -1875,8 +1885,6 @@ void silc_server_packet_send_to_channel(SilcServer server, /* Send to locally connected client */ if (client) { - /* XXX Check client's mode on the channel. */ - /* Get data used in packet header encryption, keys and stuff. */ sock = (SilcSocketConnection)client->connection; cipher = client->send_key; @@ -1913,7 +1921,7 @@ void silc_server_packet_relay_to_channel(SilcServer server, unsigned int data_len, int force_send) { - int i, found = FALSE; + int found = FALSE; SilcSocketConnection sock = NULL; SilcPacketContext packetdata; SilcClientEntry client = NULL; @@ -2051,7 +2059,6 @@ void silc_server_packet_send_local_channel(SilcServer server, unsigned int data_len, int force_send) { - int i; SilcClientEntry client; SilcChannelClientEntry chl; SilcSocketConnection sock = NULL; @@ -2245,7 +2252,6 @@ void silc_server_remove_from_channels(SilcServer server, SilcSocketConnection sock, SilcClientEntry client) { - int i, k; SilcChannelEntry channel; SilcChannelClientEntry chl; SilcBuffer chidp, clidp; @@ -2259,52 +2265,43 @@ void silc_server_remove_from_channels(SilcServer server, /* Remove the client from all channels. The client is removed from the channels' user list. */ - for (i = 0; i < client->channel_count; i++) { - channel = client->channel[i]; - if (!channel) - continue; - + silc_list_start(client->channels); + while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) { + channel = chl->channel; chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL); - /* Remove from channel */ - silc_list_start(channel->user_list); - while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) { - if (chl->client == client) { - - /* If this client is last one on the channel the channel - is removed all together. */ - if (silc_list_count(channel->user_list) == 1) { - - /* However, if the channel has marked global users then the - channel is not created locally, and this does not remove the - channel globally from SILC network, in this case we will - notify that this client has left the channel. */ - if (channel->global_users) - silc_server_send_notify_to_channel(server, channel, - SILC_NOTIFY_TYPE_SIGNOFF, 1, - clidp->data, clidp->len); - - silc_idlist_del_channel(server->local_list, channel); - break; - } + /* Remove from list */ + silc_list_del(client->channels, chl); - silc_list_del(channel->user_list, chl); - silc_free(chl); + /* If this client is last one on the channel the channel + is removed all together. */ + if (silc_list_count(channel->user_list) < 2) { - /* Send notify to channel about client leaving SILC and thus - the entire channel. */ + /* However, if the channel has marked global users then the + channel is not created locally, and this does not remove the + channel globally from SILC network, in this case we will + notify that this client has left the channel. */ + if (channel->global_users) silc_server_send_notify_to_channel(server, channel, SILC_NOTIFY_TYPE_SIGNOFF, 1, clidp->data, clidp->len); - } + + silc_idlist_del_channel(server->local_list, channel); + continue; } + /* Remove from list */ + silc_list_del(channel->user_list, chl); + silc_free(chl); + + /* Send notify to channel about client leaving SILC and thus + the entire channel. */ + silc_server_send_notify_to_channel(server, channel, + SILC_NOTIFY_TYPE_SIGNOFF, 1, + clidp->data, clidp->len); silc_buffer_free(chidp); } - if (client->channel_count) - silc_free(client->channel); - client->channel = NULL; silc_buffer_free(clidp); } @@ -2320,7 +2317,6 @@ int silc_server_remove_from_one_channel(SilcServer server, SilcClientEntry client, int notify) { - int i, k; SilcChannelEntry ch; SilcChannelClientEntry chl; SilcBuffer clidp; @@ -2331,43 +2327,41 @@ int silc_server_remove_from_one_channel(SilcServer server, /* Remove the client from the channel. The client is removed from the channel's user list. */ - for (i = 0; i < client->channel_count; i++) { - ch = client->channel[i]; - if (!ch || ch != channel) + silc_list_start(client->channels); + while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) { + if (chl->channel != channel) continue; - client->channel[i] = NULL; + ch = chl->channel; - /* Remove from channel */ - silc_list_start(channel->user_list); - while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) { - if (chl->client == client) { - - /* If this client is last one on the channel the channel - is removed all together. */ - if (silc_list_count(channel->user_list) == 1) { - /* Notify about leaving client if this channel has global users, - ie. the channel is not created locally. */ - if (notify && channel->global_users) - silc_server_send_notify_to_channel(server, channel, - SILC_NOTIFY_TYPE_LEAVE, 1, - clidp->data, clidp->len); - - silc_idlist_del_channel(server->local_list, channel); - silc_buffer_free(clidp); - return FALSE; - } - - silc_list_del(channel->user_list, chl); - silc_free(chl); - - /* Send notify to channel about client leaving the channel */ - if (notify) - silc_server_send_notify_to_channel(server, channel, - SILC_NOTIFY_TYPE_LEAVE, 1, - clidp->data, clidp->len); - } + /* Remove from list */ + silc_list_del(client->channels, chl); + + /* If this client is last one on the channel the channel + is removed all together. */ + if (silc_list_count(channel->user_list) < 2) { + /* Notify about leaving client if this channel has global users, + ie. the channel is not created locally. */ + if (notify && channel->global_users) + silc_server_send_notify_to_channel(server, channel, + SILC_NOTIFY_TYPE_LEAVE, 1, + clidp->data, clidp->len); + + silc_idlist_del_channel(server->local_list, channel); + silc_buffer_free(clidp); + return FALSE; } + + /* Remove from list */ + silc_list_del(channel->user_list, chl); + silc_free(chl); + + /* Send notify to channel about client leaving the channel */ + if (notify) + silc_server_send_notify_to_channel(server, channel, + SILC_NOTIFY_TYPE_LEAVE, 1, + clidp->data, clidp->len); + break; } silc_buffer_free(clidp); @@ -2382,15 +2376,15 @@ int silc_server_remove_from_one_channel(SilcServer server, int silc_server_client_on_channel(SilcClientEntry client, SilcChannelEntry channel) { - int i; + SilcChannelClientEntry chl; if (!client || !channel) return FALSE; - for (i = 0; i < client->channel_count; i++) { - if (client->channel[i] == channel) + silc_list_start(client->channels); + while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) + if (chl->channel == channel) return TRUE; - } return FALSE; } @@ -2552,11 +2546,9 @@ void silc_server_channel_message(SilcServer server, { SilcChannelEntry channel = NULL; SilcChannelClientEntry chl; - SilcClientEntry client = NULL; SilcChannelID *id = NULL; void *sender = NULL; SilcBuffer buffer = packet->buffer; - int i; SILC_LOG_DEBUG(("Processing channel message")); @@ -2624,7 +2616,6 @@ void silc_server_channel_key(SilcServer server, unsigned char *tmp; unsigned int tmp_len; char *cipher; - int i; if (packet->src_id_type != SILC_ID_SERVER && sock->type != SILC_SOCKET_TYPE_ROUTER) @@ -2800,7 +2791,7 @@ void silc_server_send_notify_on_channels(SilcServer server, SilcNotifyType type, unsigned int argc, ...) { - int i, j, k; + int k; SilcSocketConnection sock = NULL; SilcPacketContext packetdata; SilcClientEntry c; @@ -2809,7 +2800,7 @@ void silc_server_send_notify_on_channels(SilcServer server, SilcServerEntry *routed = NULL; unsigned int routed_count = 0; SilcChannelEntry channel; - SilcChannelClientEntry chl; + SilcChannelClientEntry chl, chl2; SilcCipher cipher; SilcHmac hmac; SilcBuffer packet; @@ -2818,7 +2809,7 @@ void silc_server_send_notify_on_channels(SilcServer server, int force_send = FALSE; va_list ap; - if (!client->channel_count) + if (!silc_list_count(client->channels)) return; va_start(ap, argc); @@ -2834,16 +2825,14 @@ void silc_server_send_notify_on_channels(SilcServer server, packetdata.src_id_type = SILC_ID_SERVER; packetdata.rng = server->rng; - for (i = 0; i < client->channel_count; i++) { - channel = client->channel[i]; + silc_list_start(client->channels); + while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) { + channel = chl->channel; - if (!channel) - continue; - - /* Send the message to clients on the channel's client list. */ + /* Send the message to all clients on the channel's client list. */ silc_list_start(channel->user_list); - while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) { - c = chl->client; + while ((chl2 = silc_list_get(channel->user_list)) != SILC_LIST_END) { + c = chl2->client; /* Check if we have sent the packet to this client already */ for (k = 0; k < sent_clients_count; k++) @@ -3151,12 +3140,6 @@ SilcChannelEntry silc_server_new_channel(SilcServer server, return NULL; } -#if 0 - /* Add to cache */ - silc_idcache_add(server->local_list->channels, channel_name, - SILC_ID_CHANNEL, channel_id, (void *)entry, TRUE); -#endif - entry->key = silc_calloc(key_len, sizeof(*entry->key)); entry->key_len = key_len * 8; memcpy(entry->key, channel_key, key_len); diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index 0093ac84..e0c037e8 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -82,9 +82,8 @@ typedef struct SilcServerObjectStruct { SilcServerStatistics stats; #ifdef SILC_SIM - /* SIM (SILC Module) table */ - SilcSimContext **sim; - unsigned int sim_count; + /* SIM (SILC Module) list */ + SilcDList sim; #endif } SilcServerObject; diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index fc89bace..34985bad 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -20,6 +20,13 @@ /* * $Id$ * $Log$ + * Revision 1.5 2000/11/02 22:15:23 priikone + * Some bugfixes. + * Changed server->sim to SilcDList and code accordingly. + * Changes SilcClientEntry->channel to SilcList and added + * back-pointer to SilcChannelClientEntry which is now used by both + * client entry and channel entry + * * Revision 1.4 2000/10/06 08:10:23 priikone * Added WHOIS to send multiple replies if multiple nicknames are * found. @@ -1203,12 +1210,8 @@ void silc_config_server_register_ciphers(SilcConfigServer config) SILC_CIPHER_SIM_CONTEXT_LEN)); SILC_LOG_DEBUG(("context_len=%p", cipher.context_len)); - /* Put the SIM to the table of all SIM's in server */ - server->sim = silc_realloc(server->sim, - sizeof(*server->sim) * - (server->sim_count + 1)); - server->sim[server->sim_count] = sim; - server->sim_count++; + /* Put the SIM to the list of all SIM's in server */ + silc_dlist_add(server->sim, sim); } else { SILC_LOG_ERROR(("Error configuring ciphers")); silc_server_stop(server); @@ -1310,11 +1313,7 @@ void silc_config_server_register_hashfuncs(SilcConfigServer config) SILC_LOG_DEBUG(("context_len=%p", hash.context_len)); /* Put the SIM to the table of all SIM's in server */ - server->sim = silc_realloc(server->sim, - sizeof(*server->sim) * - (server->sim_count + 1)); - server->sim[server->sim_count] = sim; - server->sim_count++; + silc_dlist_add(server->sim, sim); } else { SILC_LOG_ERROR(("Error configuring hash functions")); silc_server_stop(server); -- 2.24.0