+ /* Backup router */
+ if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
+ if (ctx->sock == sock) {
+ silc_socket_free(sock); /* unref */
+ ctx->sock = NULL;
+ }
+
+ /* If failed after 10 attempts, it won't work, give up */
+ if (ctx->initiator_restart > 10)
+ ctx->received_failure = TRUE;
+
+ if (!ctx->received_failure) {
+ /* Protocol error, probably timeout. Just restart the protocol. */
+ SilcServerBackupProtocolContext proto_ctx;
+
+ /* Restart the protocol. */
+ proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
+ proto_ctx->server = server;
+ proto_ctx->sock = silc_socket_dup(sock);
+ proto_ctx->responder = FALSE;
+ proto_ctx->type = SILC_SERVER_BACKUP_START;
+ proto_ctx->start = time(0);
+ proto_ctx->initiator_restart = ctx->initiator_restart + 1;
+
+ /* Start through scheduler */
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_connected_later,
+ proto_ctx, 5, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ } else {
+ /* If failure was received, switch back to normal backup router.
+ For some reason primary wouldn't accept that we were supposed
+ to perfom resuming protocol. */
+ server->server_type = SILC_BACKUP_ROUTER;
+ silc_server_local_servers_toggle_enabled(server, FALSE);
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ silc_server_update_servers_by_server(server, server->id_entry,
+ sock->user_data);
+ silc_server_update_clients_by_server(server, NULL,
+ sock->user_data, TRUE);
+
+ /* Announce our clients and channels to the router */
+ silc_server_announce_clients(server, 0, sock);
+ silc_server_announce_channels(server, 0, sock);
+
+ /* Announce WATCH list a little later */
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_announce_watches,
+ silc_socket_dup(sock), 5, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
+
+ continue;
+ }
+ }
+
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ }
+ }
+
+ if (!error) {
+ SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
+
+ if (ctx->type == SILC_SERVER_BACKUP_RESUMED && server->router) {
+ /* Announce all of our information to the router. */
+ if (server->server_type == SILC_ROUTER)
+ silc_server_announce_servers(server, FALSE, 0,
+ server->router->connection);
+
+ /* Announce our clients and channels to the router */
+ silc_server_announce_clients(server, 0, server->router->connection);
+ silc_server_announce_channels(server, 0, server->router->connection);
+
+ /* Announce WATCH list a little later */
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_announce_watches,
+ silc_socket_dup(server->router->connection), 4, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ }
+ } else {
+ /* Error */
+
+ if (server->server_type == SILC_SERVER) {
+ /* If we are still using backup router Send confirmation to backup
+ that using it is still ok and continue sending traffic there.
+ The backup will reply with error if it's not ok. */
+ if (server->router && server->backup_primary) {
+ /* Send START_USE just in case using backup wouldn't be ok. */
+ silc_server_backup_send_start_use(server, server->router->connection,
+ FALSE);
+
+ /* Check couple of times same START_USE just in case. */
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_check_status,
+ silc_socket_dup(server->router->connection),
+ 5, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_check_status,
+ silc_socket_dup(server->router->connection),
+ 20, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_check_status,
+ silc_socket_dup(server->router->connection),
+ 60, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
+ }
+ }
+
+ if (ctx->sock && ctx->sock->protocol)
+ ctx->sock->protocol = NULL;
+ if (ctx->sock)
+ silc_socket_free(ctx->sock); /* unref */
+ silc_protocol_free(protocol);
+ silc_free(ctx->sessions);
+ silc_free(ctx);
+}
+
+SILC_TASK_CALLBACK(silc_server_backup_announce_watches)
+{
+ SilcSocketConnection sock = context;
+ SilcServer server = app_context;
+ if (sock->users > 1)
+ silc_server_announce_watches(server, sock);
+ silc_socket_free(sock);