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"));
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
channel->global_users = FALSE;
silc_free(chl);
- server->stat.my_chanclients--;
+
+ /* Update statistics */
+ if (client->connection)
+ server->stat.my_chanclients--;
+ if (server->server_type == SILC_ROUTER) {
+ server->stat.cell_chanclients--;
+ server->stat.chanclients--;
+ }
/* If there is not at least one local user on the channel then we don't
need the channel entry anymore, we can remove it safely, unless the
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))
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"));
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);
}
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
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;
}
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
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;
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++)
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
if (delchan) {
SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
+ /* Update statistics */
+ if (server->server_type == SILC_ROUTER)
+ server->stat.chanclients -= channel->user_count;
+
/* Totally delete the channel and all users on the channel. The
users are deleted automatically in silc_idlist_del_channel. */
silc_schedule_task_del_by_context(server->schedule, channel->rekey);
- if (silc_idlist_del_channel(server->local_list, channel))
+ if (silc_idlist_del_channel(server->local_list, channel)) {
server->stat.my_channels--;
- else
- silc_idlist_del_channel(server->global_list, channel);
+ if (server->server_type == SILC_ROUTER) {
+ server->stat.channels--;
+ server->stat.cell_channels--;
+ }
+ } else {
+ if (silc_idlist_del_channel(server->global_list, channel))
+ if (server->server_type == SILC_ROUTER)
+ server->stat.channels--;
+ }
+
return FALSE;
}
silc_hash_table_del(chl->client->channels, channel);
silc_hash_table_del(channel->user_list, chl->client);
channel->user_count--;
+
+ /* Update statistics */
+ if (chl->client->connection)
+ server->stat.my_chanclients--;
+ if (server->server_type == SILC_ROUTER) {
+ server->stat.cell_chanclients--;
+ server->stat.chanclients--;
+ }
+
silc_free(chl);
}
silc_hash_table_list_reset(&htl);
("Your host is %s, running version %s",
server->server_name, server_version));
- if (server->stat.clients && server->stat.servers + 1)
+ if (server->server_type == SILC_ROUTER) {
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
- ("There are %d clients on %d servers in SILC "
- "Network", server->stat.clients,
- server->stat.servers + 1));
+ ("There are %d clients, %d servers and %d "
+ "routers in SILC Network",
+ server->stat.clients, server->stat.servers + 1,
+ server->stat.routers));
+ } else {
+ if (server->stat.clients && server->stat.servers + 1)
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("There are %d clients, %d servers and %d "
+ "routers in SILC Network",
+ server->stat.clients, server->stat.servers + 1,
+ (server->standalone ? 0 :
+ !server->stat.routers ? 1 :
+ server->stat.routers)));
+ }
+
if (server->stat.cell_clients && server->stat.cell_servers + 1)
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("There are %d clients on %d server in our cell",
server->stat.my_clients,
server->stat.my_channels,
server->stat.my_servers,
- server->stat.my_routers + 1));
+ server->stat.my_routers));
} else {
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("I have %d clients and %d channels formed",
SILC_LOG_DEBUG(("Start"));
- silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
- server->id, SILC_ID_SERVER,
- chl->client->id, NULL);
+ if (sock)
+ silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
+ server->id, SILC_ID_SERVER,
+ chl->client->id, NULL);
idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);