X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fserver_util.c;h=c041ffb0caa822e980c4f69fc326021b19b7b5b6;hb=ea35a2214bc62cbdb314cd28f389fd78fe3a31e0;hp=e7bff22110e2b36b0d18a94f4b26379bc2bafd2e;hpb=0ce860039dc7ed06843e9182faa4d92a4bf0c005;p=silc.git diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index e7bff221..c041ffb0 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -28,14 +28,16 @@ extern char *server_version; keys are regnerated. This is called only by the function silc_server_remove_clients_by_server. */ -static void silc_server_remove_clients_channels(SilcServer server, - SilcSocketConnection sock, - SilcClientEntry client, - SilcHashTable channels) +static void +silc_server_remove_clients_channels(SilcServer server, + SilcServerEntry server_entry, + SilcHashTable clients, + SilcClientEntry client, + SilcHashTable channels) { SilcChannelEntry channel; - SilcChannelClientEntry chl; - SilcHashTableList htl; + SilcChannelClientEntry chl, chl2; + SilcHashTableList htl, htl2; SilcBuffer clidp; SILC_LOG_DEBUG(("Start")); @@ -43,6 +45,9 @@ static void silc_server_remove_clients_channels(SilcServer server, if (!client || !client->id) return; + if (silc_hash_table_find(clients, client, NULL, NULL)) + silc_hash_table_del(clients, client); + clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); /* Remove the client from all channels. The client is removed from @@ -94,6 +99,21 @@ static void silc_server_remove_clients_channels(SilcServer server, continue; } + /* Mark other local clients to the table of clients whom will receive + the SERVER_SIGNOFF notify. */ + silc_hash_table_list(channel->user_list, &htl2); + while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) { + SilcClientEntry c = chl2->client; + if (!c) + continue; + + /* Add client to table, if it's not from the signoff server */ + if (c->router != server_entry && + !silc_hash_table_find(clients, c, NULL, NULL)) + silc_hash_table_add(clients, c, c); + } + silc_hash_table_list_reset(&htl2); + /* Add the channel to the the channels list to regenerate the channel key */ if (!silc_hash_table_find(channels, channel, NULL, NULL)) @@ -117,13 +137,11 @@ bool silc_server_remove_clients_by_server(SilcServer server, SilcIDCacheEntry id_cache = NULL; SilcClientEntry client = NULL; SilcBuffer idp; - SilcClientEntry *clients = NULL; - SilcUInt32 clients_c = 0; unsigned char **argv = NULL; SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0; SilcHashTableList htl; SilcChannelEntry channel; - SilcHashTable channels; + SilcHashTable channels, clients; int i; SILC_LOG_DEBUG(("Start")); @@ -133,6 +151,8 @@ bool silc_server_remove_clients_by_server(SilcServer server, from the channels. */ channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); + clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL, + NULL, NULL, TRUE); if (server_signoff) { idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER); @@ -160,13 +180,6 @@ bool silc_server_remove_clients_by_server(SilcServer server, } if (client->router != entry) { - if (server_signoff) { - clients = silc_realloc(clients, - sizeof(*clients) * (clients_c + 1)); - clients[clients_c] = client; - clients_c++; - } - if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -196,7 +209,8 @@ bool silc_server_remove_clients_by_server(SilcServer server, SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); /* Remove the client entry */ - silc_server_remove_clients_channels(server, NULL, client, channels); + silc_server_remove_clients_channels(server, entry, clients, + client, channels); if (!server_signoff) { client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF; @@ -226,13 +240,6 @@ bool silc_server_remove_clients_by_server(SilcServer server, } if (client->router != entry) { - if (server_signoff && client->connection) { - clients = silc_realloc(clients, - sizeof(*clients) * (clients_c + 1)); - clients[clients_c] = client; - clients_c++; - } - if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -262,7 +269,8 @@ bool silc_server_remove_clients_by_server(SilcServer server, SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); /* Remove the client entry */ - silc_server_remove_clients_channels(server, NULL, client, channels); + silc_server_remove_clients_channels(server, entry, clients, + client, channels); if (!server_signoff) { client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF; @@ -295,17 +303,18 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_buffer_free(args); } + + /* Send to local clients. We also send the list of client ID's that is to be removed for those servers that would like to use that list. */ args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types); not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, argc, args); - silc_server_packet_send_clients(server, clients, clients_c, + silc_server_packet_send_clients(server, clients, SILC_PACKET_NOTIFY, 0, FALSE, not->data, not->len, FALSE); - silc_free(clients); silc_buffer_free(args); silc_buffer_free(not); for (i = 0; i < argc; i++) @@ -313,6 +322,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_free(argv); silc_free(argv_lens); silc_free(argv_types); + silc_hash_table_free(clients); } /* We must now re-generate the channel key for all channels that had