+ silc_server_packet_send_dest(server, backup->connection, type, flags,
+ dst_id, dst_id_type, data, data_len);
+ }
+}
+
+/* Send the START_USE indication to remote connection. If `failure' is
+ TRUE then this sends SILC_PACKET_FAILURE. Otherwise it sends
+ SILC_PACKET_RESUME_ROUTER. */
+
+void silc_server_backup_send_start_use(SilcServer server,
+ SilcPacketStream sock,
+ SilcBool failure)
+{
+ unsigned char data[4];
+
+ SILC_LOG_DEBUG(("Sending START_USE (%s)",
+ failure ? "failure" : "success"));
+
+ if (failure) {
+ SILC_PUT32_MSB(SILC_SERVER_BACKUP_START_USE, data);
+ silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
+ data, 4);
+ } else {
+ data[0] = SILC_SERVER_BACKUP_START_USE;
+ data[1] = 0;
+ silc_server_packet_send(server, sock,
+ SILC_PACKET_RESUME_ROUTER, 0,
+ data, 2);
+ }
+}
+
+/* Send the REPLACED indication to remote router. This is send by the
+ primary router (remote router) of the primary router that came back
+ online. This is not sent by backup router or any other server. */
+
+void silc_server_backup_send_replaced(SilcServer server,
+ SilcPacketStream sock)
+{
+ unsigned char data[4];
+
+ SILC_LOG_DEBUG(("Sending REPLACED"));
+
+ data[0] = SILC_SERVER_BACKUP_REPLACED;
+ data[1] = 0;
+ silc_server_packet_send(server, sock,
+ SILC_PACKET_RESUME_ROUTER, 0,
+ data, 2);
+}
+
+
+/************************ Backup Resuming Protocol **************************/
+
+/* Timeout callback for protocol */
+
+SILC_TASK_CALLBACK(silc_server_backup_timeout)
+{
+ SilcServerBackupProtocolContext ctx = context;
+ SilcServer server = app_context;
+
+ SILC_LOG_INFO(("Timeout occurred during backup resuming protocol"));
+ ctx->timeout = TRUE;
+ ctx->error = TRUE;
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_protocol_backup_done, context,
+ 0, 0);
+}
+
+/* Callback to start the protocol as responder */
+
+SILC_TASK_CALLBACK(silc_server_backup_responder_start)
+{
+ SilcServerBackupProtocolContext proto_ctx = context;
+ SilcPacketStream sock = proto_ctx->sock;
+ SilcIDListData idata = silc_packet_get_context(sock);
+ SilcServer server = app_context;
+
+ /* If other protocol is executing at the same time, start with timeout. */
+ if (idata->sconn->op) {
+ SILC_LOG_DEBUG(("Other protocol is executing, wait for it to finish"));
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_responder_start,
+ proto_ctx, 2, 0);
+ return;
+ }
+
+ /* Register protocol timeout */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_timeout,
+ proto_ctx, 30, 0);
+
+ /* Run the backup resuming protocol */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_protocol_backup,
+ proto_ctx, 0, 0);
+}
+
+/* Callback to send START_USE to backup to check whether using backup
+ is ok. */