+
+ if (server->server_shutdown)
+ return;
+
+ /* Remove this protocol from all server entries that has it */
+ list = silc_packet_engine_get_streams(server->packet_engine);
+ if (!list)
+ return;
+
+ silc_dlist_start(list);
+ while ((sock = silc_dlist_get(list))) {
+ server_entry = silc_packet_get_context(sock);
+ if (!server_entry)
+ continue;
+
+ if (server_entry->data.conn_type != SILC_CONN_ROUTER &&
+ server_entry->data.conn_type != SILC_CONN_SERVER)
+ continue;
+
+ if (server_entry->backup_proto == ctx) {
+ if (error) {
+
+ if (server->server_type == SILC_SERVER &&
+ server_entry->server_type == SILC_ROUTER)
+ continue;
+
+ /* Backup router */
+ if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
+ if (ctx->sock == sock) {
+ silc_packet_stream_unref(sock);
+ 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 = 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;
+ silc_packet_stream_ref(sock);
+
+ /* Start through scheduler */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_connected_later,
+ proto_ctx, 5, 0);
+ } 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,
+ silc_packet_get_context(sock));
+ silc_server_update_clients_by_server(server, NULL,
+ silc_packet_get_context(sock),
+ 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_packet_stream_ref(sock);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_announce_watches,
+ sock, 5, 0);
+ }
+
+ continue;
+ }
+ }
+
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ }