if (channel->rekey)
silc_schedule_task_del_by_context(server->schedule, channel->rekey);
- if (!silc_idlist_del_channel(server->local_list, channel))
- silc_idlist_del_channel(server->global_list, channel);
- server->stat.my_channels--;
+ if (silc_idlist_del_channel(server->local_list, channel))
+ server->stat.my_channels--;
+ else
+ silc_idlist_del_channel(server->global_list, channel);
continue;
}
SilcChannelClientEntry chl2;
SilcHashTableList htl2;
- channel->id = NULL;
+ channel->disabled = TRUE;
silc_hash_table_list(channel->user_list, &htl2);
while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
}
/* Remove the channel entry */
- if (!silc_idlist_del_channel(server->local_list, channel))
- silc_idlist_del_channel(server->global_list, channel);
- server->stat.my_channels--;
+ if (silc_idlist_del_channel(server->local_list, channel))
+ server->stat.my_channels--;
+ else
+ silc_idlist_del_channel(server->global_list, channel);
continue;
}
}
if (client->router != entry) {
- if (server_signoff && client->connection) {
+ if (server_signoff) {
clients = silc_realloc(clients,
sizeof(*clients) * (clients_c + 1));
clients[clients_c] = client;
/* Remove the client entry */
silc_server_remove_clients_channels(server, NULL, client, channels);
- silc_idlist_del_client(server->local_list, client);
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+ server->stat.clients--;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.cell_clients--;
if (!silc_idcache_list_next(list, &id_cache))
break;
/* Remove the client entry */
silc_server_remove_clients_channels(server, NULL, client, channels);
- silc_idlist_del_client(server->global_list, client);
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+ server->stat.clients--;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.cell_clients--;
if (!silc_idcache_list_next(list, &id_cache))
break;
/* Send the SERVER_SIGNOFF notify */
if (server_signoff) {
- SilcBuffer args;
+ SilcBuffer args, not;
/* Send SERVER_SIGNOFF notify to our primary router */
if (!server->standalone && server->router &&
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);
- /* Send to local clients */
- for (i = 0; i < clients_c; i++) {
- silc_server_send_notify_args(server, clients[i]->connection,
- FALSE, SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
- argc, args);
- }
+ not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+ argc, args);
+ silc_server_packet_send_clients(server, clients, clients_c,
+ 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[i]);
silc_free(argv);
static SilcServerEntry
silc_server_update_clients_by_real_server(SilcServer server,
- SilcClientEntry client)
+ SilcServerEntry from,
+ SilcClientEntry client,
+ bool local,
+ SilcIDCacheEntry client_cache)
{
SilcServerEntry server_entry;
SilcIDCacheEntry id_cache = NULL;
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
- if (SILC_ID_COMPARE(server_entry->id, client->id,
+ if (server_entry != from &&
+ SILC_ID_COMPARE(server_entry->id, client->id,
+ client->id->ip.data_len)) {
+ SILC_LOG_DEBUG(("Found (local) %s",
+ silc_id_render(server_entry->id, SILC_ID_SERVER)));
+
+ if (!server_entry->data.send_key && server_entry->router) {
+ SILC_LOG_DEBUG(("Server not locally connected, use its router"));
+ /* If the client is not marked as local then move it to local list
+ since the server is local. */
+ if (!local) {
+ SILC_LOG_DEBUG(("Moving client to local list"));
+ silc_idcache_add(server->local_list->clients, client_cache->name,
+ client_cache->id, client_cache->context,
+ client_cache->expire);
+ silc_idcache_del_by_context(server->global_list->clients, client);
+ }
+ server_entry = server_entry->router;
+ } else {
+ /* If the client is not marked as local then move it to local list
+ since the server is local. */
+ if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
+ SILC_LOG_DEBUG(("Moving client to local list"));
+ silc_idcache_add(server->local_list->clients, client_cache->name,
+ client_cache->id, client_cache->context,
+ client_cache->expire);
+ silc_idcache_del_by_context(server->global_list->clients, client);
+ }
+ }
+
+ silc_idcache_list_free(list);
+ return server_entry;
+ }
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ }
+
+ silc_idcache_list_free(list);
+
+ if (!silc_idcache_get_all(server->global_list->servers, &list))
+ return NULL;
+
+ if (silc_idcache_list_first(list, &id_cache)) {
+ while (id_cache) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (server_entry != from &&
+ SILC_ID_COMPARE(server_entry->id, client->id,
client->id->ip.data_len)) {
- SILC_LOG_DEBUG(("Found"));
+ SILC_LOG_DEBUG(("Found (global) %s",
+ silc_id_render(server_entry->id, SILC_ID_SERVER)));
+
+ if (!server_entry->data.send_key && server_entry->router) {
+ SILC_LOG_DEBUG(("Server not locally connected, use its router"));
+ /* If the client is marked as local then move it to global list
+ since the server is global. */
+ if (local) {
+ SILC_LOG_DEBUG(("Moving client to global list"));
+ silc_idcache_add(server->global_list->clients, client_cache->name,
+ client_cache->id, client_cache->context,
+ client_cache->expire);
+ silc_idcache_del_by_context(server->local_list->clients, client);
+ }
+ server_entry = server_entry->router;
+ } else {
+ /* If the client is marked as local then move it to global list
+ since the server is global. */
+ if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
+ SILC_LOG_DEBUG(("Moving client to global list"));
+ silc_idcache_add(server->global_list->clients, client_cache->name,
+ client_cache->id, client_cache->context,
+ client_cache->expire);
+ silc_idcache_del_by_context(server->local_list->clients, client);
+ }
+ }
+
silc_idcache_list_free(list);
return server_entry;
}
SilcIDCacheList list = NULL;
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry client = NULL;
+ bool local;
SILC_LOG_DEBUG(("Start"));
- if (silc_idcache_get_all(server->local_list->clients, &list)) {
+ SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
+ SILC_ID_SERVER)));
+ SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
+ SILC_ID_SERVER)));
+
+
+ local = FALSE;
+ if (silc_idcache_get_all(server->global_list->clients, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
client = (SilcClientEntry)id_cache->context;
continue;
}
+ SILC_LOG_DEBUG(("Client (global) %s",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
+ if (client->router)
+ SILC_LOG_DEBUG(("Client->router (global) %s",
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
+
if (client->router == from) {
/* Skip clients that are *really* owned by the `from' */
- if (SILC_ID_COMPARE(from->id, client->id,
- client->id->ip.data_len)) {
+ if (remove_from && SILC_ID_COMPARE(from->id, client->id,
+ client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found really owned client, skip it"));
if (!silc_idcache_list_next(list, &id_cache))
break;
if (resolve_real_server) {
client->router =
- silc_server_update_clients_by_real_server(server, client);
+ silc_server_update_clients_by_real_server(server, from, client,
+ local, id_cache);
if (!client->router)
client->router = to;
} else {
silc_idcache_list_free(list);
}
- if (silc_idcache_get_all(server->global_list->clients, &list)) {
+ local = TRUE;
+ if (silc_idcache_get_all(server->local_list->clients, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
client = (SilcClientEntry)id_cache->context;
continue;
}
+ SILC_LOG_DEBUG(("Client (local) %s",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
+ if (client->router)
+ SILC_LOG_DEBUG(("Client->router (local) %s",
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
+
if (client->router == from) {
/* Skip clients that are *really* owned by the `from' */
- if (SILC_ID_COMPARE(from->id, client->id,
- client->id->ip.data_len)) {
+ if (remove_from && SILC_ID_COMPARE(from->id, client->id,
+ client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found really owned client, skip it"));
if (!silc_idcache_list_next(list, &id_cache))
break;
if (resolve_real_server) {
client->router =
- silc_server_update_clients_by_real_server(server, client);
+ silc_server_update_clients_by_real_server(server, from, client,
+ local, id_cache);
if (!client->router)
- client->router = to;
+ client->router = from; /* on local list put old from */
} else {
client->router = to;
}
silc_server_remove_clients_by_server(server, from, TRUE);
}
+/* Updates servers that are from `from' to be originated from `to'. This
+ will also update the server's connection to `to's connection. */
+
+void silc_server_update_servers_by_server(SilcServer server,
+ SilcServerEntry from,
+ SilcServerEntry to)
+{
+ SilcIDCacheList list = NULL;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server_entry = NULL;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ if (silc_idcache_get_all(server->local_list->servers, &list)) {
+ if (silc_idcache_list_first(list, &id_cache)) {
+ while (id_cache) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (server_entry->router == from) {
+ server_entry->router = to;
+ server_entry->connection = to->connection;
+ }
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ }
+ silc_idcache_list_free(list);
+ }
+
+ if (silc_idcache_get_all(server->global_list->servers, &list)) {
+ if (silc_idcache_list_first(list, &id_cache)) {
+ while (id_cache) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (server_entry->router == from) {
+ server_entry->router = to;
+ server_entry->connection = to->connection;
+ }
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ }
+ silc_idcache_list_free(list);
+ }
+}
+
/* Checks whether given channel has global users. If it does this returns
TRUE and FALSE if there is only locally connected clients on the channel. */