-
- /* Free all client entries that this server owns as they will
- become invalid now as well. */
- silc_server_remove_clients_by_server(server, user_data, TRUE);
-
- /* If this was our primary router connection then we're lost to
- the outside world. */
- if (server->router == user_data) {
- server->id_entry->router = NULL;
- server->router = NULL;
- server->standalone = TRUE;
- }
-
- /* Free the server entry */
- silc_idlist_del_data(user_data);
- silc_idlist_del_server(server->local_list, user_data);
- server->stat.my_servers--;
- server->stat.servers--;
- if (server->server_type == SILC_ROUTER)
- server->stat.cell_servers--;
- break;
- }
- default:
- {
- SilcUnknownEntry user_data = (SilcUnknownEntry)sock->user_data;
-
- silc_idlist_del_data(user_data);
- silc_free(user_data);
- break;
- }
- }
-
- sock->user_data = NULL;
-}
-
-/* This function is used to remove all client entries by the server `entry'.
- This is called when the connection is lost to the server. In this case
- we must invalidate all the client entries owned by the server `entry'.
- If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
- distributed to our local clients. */
-
-int silc_server_remove_clients_by_server(SilcServer server,
- SilcServerEntry entry,
- int server_signoff)
-{
- SilcIDCacheList list = NULL;
- SilcIDCacheEntry id_cache = NULL;
- SilcClientEntry client = NULL;
- SilcBuffer idp;
- SilcClientEntry *clients = NULL;
- uint32 clients_c = 0;
- unsigned char **argv = NULL;
- uint32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
- int i;
-
- SILC_LOG_DEBUG(("Start"));
-
- if (server_signoff) {
- idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
- argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
- argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
- argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
- argv[argc] = idp->data;
- argv_lens[argc] = idp->len;
- argv_types[argc] = argc + 1;
- argc++;
- silc_buffer_free(idp);
- }
-
- if (silc_idcache_find_by_id(server->local_list->clients,
- SILC_ID_CACHE_ANY, SILC_ID_CLIENT, &list)) {
-
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- client = (SilcClientEntry)id_cache->context;
- if (client->data.registered == FALSE) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- 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
- continue;
- }
-
- if (server_signoff) {
- idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
- argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
- (argc + 1));
- argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
- (argc + 1));
- argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
- memcpy(argv[argc], idp->data, idp->len);
- argv_lens[argc] = idp->len;
- argv_types[argc] = argc + 1;
- argc++;
- silc_buffer_free(idp);
- }
-
- /* Remove the client entry */
- silc_server_remove_from_channels(server, NULL, client, FALSE,
- NULL, FALSE);
- silc_idlist_del_client(server->local_list, client);
-
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- }
- }
- silc_idcache_list_free(list);
- }
-
- if (silc_idcache_find_by_id(server->global_list->clients,
- SILC_ID_CACHE_ANY, SILC_ID_CLIENT, &list)) {
-
- if (silc_idcache_list_first(list, &id_cache)) {
- while (id_cache) {
- client = (SilcClientEntry)id_cache->context;
- if (client->data.registered == FALSE) {
- if (!silc_idcache_list_next(list, &id_cache))
- break;
- else
- continue;
- }
-
- if (client->router != entry) {
- if (server_signoff && client->connection) {
- clients = silc_realloc(clients,
- sizeof(*clients) * (clients_c + 1));
- clients[clients_c] = client;
- clients_c++;
+ SilcServerEntry backup_router = NULL;
+
+ /* If this was our primary router connection then we're lost to
+ the outside world. */
+ if (server->router == user_data) {
+ backup_router = silc_server_backup_get(server);
+
+ /* Check whether we have a backup router connection */
+ if (!backup_router || backup_router == user_data) {
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router,
+ server, 1, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+
+ server->id_entry->router = NULL;
+ server->router = NULL;
+ server->standalone = TRUE;
+ backup_router = NULL;
+ } else {
+ SILC_LOG_INFO(("New primary router is backup router %s",
+ backup_router->server_name));
+ SILC_LOG_DEBUG(("New primary router is backup router %s",
+ backup_router->server_name));
+ server->id_entry->router = backup_router;
+ server->router = backup_router;
+ server->router_connect = time(0);
+ if (server->server_type == SILC_BACKUP_ROUTER) {
+ server->server_type = SILC_ROUTER;
+
+ /* We'll need to constantly try to reconnect to the primary
+ router so that we'll see when it comes back online. */
+ silc_server_backup_reconnect(server, sock->ip, sock->port,
+ silc_server_backup_connected,
+ NULL);