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;
- SilcBuffer clidp;
+ SilcChannelClientEntry chl, chl2;
+ SilcHashTableList htl, htl2;
SILC_LOG_DEBUG(("Start"));
- if (!client || !client->id)
+ if (!client)
return;
- clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ if (silc_hash_table_find(clients, client, NULL, NULL))
+ silc_hash_table_del(clients, client);
/* Remove the client from all channels. The client is removed from
the channels' user list. */
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))
silc_hash_table_add(channels, channel, channel);
}
silc_hash_table_list_reset(&htl);
- silc_buffer_free(clidp);
}
/* This function is used to remove all client entries by the server `entry'.
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, server, SILC_UMODE_SERVER_OPERATOR);
SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
+ silc_server_remove_clients_channels(server, entry, clients,
+ client, channels);
+ silc_server_del_from_watcher_list(server, client);
+
/* Remove the client entry */
- silc_server_remove_clients_channels(server, NULL, client, channels);
if (!server_signoff) {
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
} else {
- /* Remove this client from watcher list if it is */
- silc_server_del_from_watcher_list(server, client);
silc_idlist_del_client(server->local_list, client);
}
}
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, server, SILC_UMODE_SERVER_OPERATOR);
SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
+ silc_server_remove_clients_channels(server, entry, clients,
+ client, channels);
+ silc_server_del_from_watcher_list(server, client);
+
/* Remove the client entry */
- silc_server_remove_clients_channels(server, NULL, client, channels);
if (!server_signoff) {
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
SilcBuffer args, not;
/* Send SERVER_SIGNOFF notify to our primary router */
- if (!server->standalone && server->router &&
- server->router != entry) {
+ if (server->router != entry) {
args = silc_argument_payload_encode(1, argv, argv_lens,
argv_types);
- silc_server_send_notify_args(server,
- server->router->connection,
- server->server_type == SILC_SERVER ?
- FALSE : TRUE,
+ silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
+ SILC_BROADCAST(server),
SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
argc, args);
silc_buffer_free(args);
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);
}
if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
- if (is_op && !is_fo)
- return FALSE;
+ if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
} else {
if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
if (is_op && !is_fo)
}
if (mode & SILC_CHANNEL_MODE_CIPHER) {
- if (is_op && !is_fo)
- return FALSE;
+ if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
} else {
if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
if (is_op && !is_fo)
}
if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
- if (is_op && !is_fo)
- return FALSE;
+ if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
} else {
if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
if (is_op && !is_fo)
}
if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
- if (is_op && !is_fo)
- return FALSE;
+ if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
} else {
if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
if (is_op && !is_fo)
}
if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
- if (is_op && !is_fo)
- return FALSE;
+ if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
+ if (is_op && !is_fo)
+ return FALSE;
+ }
} else {
if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
if (is_op && !is_fo)
{
SilcIDListData idata = (SilcIDListData)client;
+ SILC_LOG_DEBUG(("Send welcome notifys"));
+
/* Send some nice info to the client */
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Welcome to the SILC Network %s",
("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",
killer->data, killer->len);
/* Send KILLED notify to primary route */
- if (!server->standalone)
- silc_server_send_notify_killed(server, server->router->connection, TRUE,
- remote_client->id, comment,
- killer_id, killer_id_type);
+ silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
+ SILC_BROADCAST(server), remote_client->id,
+ comment, killer_id, killer_id_type);
/* Send KILLED notify to the client directly */
if (remote_client->connection || remote_client->router)
unsigned char hash[16];
WatcherNotifyContext n;
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Checking watcher list %s",
+ client->nickname ? client->nickname : (unsigned char *)""));
/* If the watching is rejected by the client do nothing */
if (client->mode & SILC_UMODE_REJECT_WATCHING)
if (entry == client) {
silc_hash_table_del_by_context(server->watcher_list, key, client);
- SILC_LOG_DEBUG(("Removing %s from WATCH list",
- silc_id_render(client->id, SILC_ID_CLIENT)));
+ if (client->id)
+ SILC_LOG_DEBUG(("Removing %s from WATCH list",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
/* Now check whether there still exists entries with this key, if not
then free the key to not leak memory. */
SilcBuffer idp1, idp2;
unsigned char cumode[4];
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Enforcing sender to change mode"));
- 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);