5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2003 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
25 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router);
27 static void silc_server_backup_connect_primary(SilcServer server,
28 SilcServerEntry server_entry,
32 /************************** Types and Definitions ***************************/
36 SilcServerEntry server;
40 } SilcServerBackupEntry;
42 /* Holds IP address and port of the primary router that was replaced
47 SilcServerEntry server; /* Backup router that replaced the primary */
48 } SilcServerBackupReplaced;
51 struct SilcServerBackupStruct {
52 SilcServerBackupEntry *servers;
53 SilcUInt32 servers_count;
54 SilcServerBackupReplaced **replaced;
55 SilcUInt32 replaced_count;
61 SilcServerEntry server_entry;
62 } SilcServerBackupProtocolSession;
64 /* Backup resuming protocol context */
67 SilcSocketConnection sock;
70 SilcServerBackupProtocolSession *sessions;
71 SilcUInt32 sessions_count;
73 unsigned int responder : 1;
74 unsigned int received_failure : 1;
75 unsigned int timeout : 1;
76 } *SilcServerBackupProtocolContext;
79 /********************* Backup Configuration Routines ************************/
81 /* Adds the `backup_server' to be one of our backup router. This can be
82 called multiple times to set multiple backup routers. The `ip' and `port'
83 is the IP and port that the `backup_router' will replace if the `ip'
84 will become unresponsive. If `local' is TRUE then the `backup_server' is
85 in the local cell, if FALSE it is in some other cell. */
87 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
88 const char *ip, int port, bool local)
95 if (!server->backup) {
96 server->backup = silc_calloc(1, sizeof(*server->backup));
101 /* See if already added */
102 for (i = 0; i < server->backup->servers_count; i++) {
103 if (server->backup->servers[i].server == backup_server)
107 SILC_LOG_DEBUG(("Backup router %s will replace %s",
108 ((SilcSocketConnection)backup_server->connection)->ip,
111 for (i = 0; i < server->backup->servers_count; i++) {
112 if (!server->backup->servers[i].server) {
113 server->backup->servers[i].server = backup_server;
114 server->backup->servers[i].local = local;
115 server->backup->servers[i].port = SILC_SWAB_16(port);
116 memset(server->backup->servers[i].ip.data, 0,
117 sizeof(server->backup->servers[i].ip.data));
118 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
119 sizeof(server->backup->servers[i].ip.data));
124 i = server->backup->servers_count;
125 server->backup->servers = silc_realloc(server->backup->servers,
126 sizeof(*server->backup->servers) *
128 server->backup->servers[i].server = backup_server;
129 server->backup->servers[i].local = local;
130 server->backup->servers[i].port = SILC_SWAB_16(port);
131 memset(server->backup->servers[i].ip.data, 0,
132 sizeof(server->backup->servers[i].ip.data));
133 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
134 sizeof(server->backup->servers[i].ip.data));
135 server->backup->servers_count++;
138 /* Returns backup router for IP and port in `server_id' or NULL if there
139 does not exist backup router. */
141 SilcServerEntry silc_server_backup_get(SilcServer server,
142 SilcServerID *server_id)
149 for (i = 0; i < server->backup->servers_count; i++) {
150 if (server->backup->servers[i].server &&
151 server->backup->servers[i].port == server_id->port &&
152 !memcmp(server->backup->servers[i].ip.data, server_id->ip.data,
153 sizeof(server_id->ip.data))) {
154 SILC_LOG_DEBUG(("Found backup router %s for %s",
155 server->backup->servers[i].server->server_name,
156 silc_id_render(server_id, SILC_ID_SERVER)));
157 return server->backup->servers[i].server;
164 /* Deletes the backup server `server_entry'. */
166 void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry)
173 for (i = 0; i < server->backup->servers_count; i++) {
174 if (server->backup->servers[i].server == server_entry) {
175 SILC_LOG_DEBUG(("Removing %s as backup router",
176 silc_id_render(server->backup->servers[i].server->id,
178 server->backup->servers[i].server = NULL;
179 memset(server->backup->servers[i].ip.data, 0,
180 sizeof(server->backup->servers[i].ip.data));
185 /* Frees all data allocated for backup routers. Call this after deleting
186 all backup routers and when new routers are added no more, for example
187 when shutting down the server. */
189 void silc_server_backup_free(SilcServer server)
196 /* Delete existing servers if caller didn't do it */
197 for (i = 0; i < server->backup->servers_count; i++) {
198 if (server->backup->servers[i].server)
199 silc_server_backup_del(server, server->backup->servers[i].server);
202 silc_free(server->backup->servers);
203 silc_free(server->backup);
204 server->backup = NULL;
207 /* Marks the IP address and port from the `server_id' as being replaced
208 by backup router indicated by the `server'. If the router connects at
209 a later time we can check whether it has been replaced by an backup
212 void silc_server_backup_replaced_add(SilcServer server,
213 SilcServerID *server_id,
214 SilcServerEntry server_entry)
217 SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
220 server->backup = silc_calloc(1, sizeof(*server->backup));
221 if (!server->backup->replaced) {
222 server->backup->replaced =
223 silc_calloc(1, sizeof(*server->backup->replaced));
224 server->backup->replaced_count = 1;
227 SILC_LOG_DEBUG(("Replacing router %s with %s",
228 silc_id_render(server_id, SILC_ID_SERVER),
229 server_entry->server_name));
231 memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
232 r->server = server_entry;
234 for (i = 0; i < server->backup->replaced_count; i++) {
235 if (!server->backup->replaced[i]) {
236 server->backup->replaced[i] = r;
241 i = server->backup->replaced_count;
242 server->backup->replaced = silc_realloc(server->backup->replaced,
243 sizeof(*server->backup->replaced) *
245 server->backup->replaced[i] = r;
246 server->backup->replaced_count++;
249 /* Checks whether the IP address and port from the `server_id' has been
250 replaced by an backup router. If it has been then this returns TRUE
251 and the bacup router entry to the `server' pointer if non-NULL. Returns
252 FALSE if the router is not replaced by backup router. */
254 bool silc_server_backup_replaced_get(SilcServer server,
255 SilcServerID *server_id,
256 SilcServerEntry *server_entry)
260 if (!server->backup || !server->backup->replaced)
263 for (i = 0; i < server->backup->replaced_count; i++) {
264 if (!server->backup->replaced[i])
266 if (!memcmp(server->backup->replaced[i]->ip.data, server_id->ip.data,
267 sizeof(server_id->ip.data))) {
269 *server_entry = server->backup->replaced[i]->server;
270 SILC_LOG_DEBUG(("Router %s is replaced by %s",
271 silc_id_render(server_id, SILC_ID_SERVER),
272 server->backup->replaced[i]->server->server_name));
277 SILC_LOG_DEBUG(("Router %s is not replaced by backup router",
278 silc_id_render(server_id, SILC_ID_SERVER)));
282 /* Deletes a replaced host by the set `server_entry. */
284 void silc_server_backup_replaced_del(SilcServer server,
285 SilcServerEntry server_entry)
289 if (!server->backup || !server->backup->replaced)
292 for (i = 0; i < server->backup->replaced_count; i++) {
293 if (!server->backup->replaced[i])
295 if (server->backup->replaced[i]->server == server_entry) {
296 silc_free(server->backup->replaced[i]);
297 server->backup->replaced[i] = NULL;
303 /* Broadcast the received packet indicated by `packet' to all of our backup
304 routers. All router wide information is passed using broadcast packets.
305 That is why all backup routers need to get this data too. It is expected
306 that the caller already knows that the `packet' is broadcast packet. */
308 void silc_server_backup_broadcast(SilcServer server,
309 SilcSocketConnection sender,
310 SilcPacketContext *packet)
312 SilcServerEntry backup;
313 SilcSocketConnection sock;
315 const SilcBufferStruct p;
316 SilcIDListData idata;
319 if (!server->backup || server->server_type != SILC_ROUTER)
322 SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
324 buffer = packet->buffer;
325 silc_buffer_push(buffer, buffer->data - buffer->head);
327 for (i = 0; i < server->backup->servers_count; i++) {
328 backup = server->backup->servers[i].server;
330 if (!backup || backup->connection == sender ||
331 server->backup->servers[i].local == FALSE)
333 if (server->backup->servers[i].server == server->id_entry)
336 idata = (SilcIDListData)backup;
337 sock = backup->connection;
339 if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
340 (const SilcBuffer)&p)) {
341 SILC_LOG_ERROR(("Cannot send packet"));
344 silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
345 silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
346 (SilcBuffer)&p, p.len);
348 SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len);
350 /* Now actually send the packet */
351 silc_server_packet_send_real(server, sock, FALSE);
353 /* Check for mandatory rekey */
354 if (idata->psn_send == SILC_SERVER_REKEY_THRESHOLD)
355 silc_schedule_task_add(server->schedule, sender->sock,
356 silc_server_rekey_callback, sender, 0, 1,
357 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
361 /* A generic routine to send data to all backup routers. If the `sender'
362 is provided it will indicate the original sender of the packet and the
363 packet won't be resent to that entity. The `data' is the data that will
364 be assembled to packet context before sending. The packet will be
365 encrypted this function. If the `force_send' is TRUE the data is sent
366 immediately and not put to queue. If `local' is TRUE then the packet
367 will be sent only to local backup routers inside the cell. If false the
368 packet can go from one cell to the other. This function has no effect
369 if there are no any backup routers. */
371 void silc_server_backup_send(SilcServer server,
372 SilcServerEntry sender,
374 SilcPacketFlags flags,
380 SilcServerEntry backup;
381 SilcSocketConnection sock;
384 if (!server->backup || server->server_type != SILC_ROUTER)
387 for (i = 0; i < server->backup->servers_count; i++) {
388 backup = server->backup->servers[i].server;
389 if (!backup || sender == backup)
391 if (local && server->backup->servers[i].local == FALSE)
393 if (server->backup->servers[i].server == server->id_entry)
396 sock = backup->connection;
398 SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
399 silc_get_packet_name(type), sock->hostname, sock->ip));
401 silc_server_packet_send(server, backup->connection, type, flags,
402 data, data_len, force_send);
406 /* Same as silc_server_backup_send but sets a specific Destination ID to
407 the packet. The Destination ID is indicated by the `dst_id' and the
408 ID type `dst_id_type'. For example, packets destined to channels must
409 be sent using this function. */
411 void silc_server_backup_send_dest(SilcServer server,
412 SilcServerEntry sender,
414 SilcPacketFlags flags,
416 SilcIdType dst_id_type,
422 SilcServerEntry backup;
423 SilcSocketConnection sock;
426 if (!server->backup || server->server_type != SILC_ROUTER)
429 for (i = 0; i < server->backup->servers_count; i++) {
430 backup = server->backup->servers[i].server;
431 if (!backup || sender == backup)
433 if (local && server->backup->servers[i].local == FALSE)
435 if (server->backup->servers[i].server == server->id_entry)
438 sock = backup->connection;
440 SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
441 silc_get_packet_name(type), sock->hostname, sock->ip));
443 silc_server_packet_send_dest(server, backup->connection, type, flags,
444 dst_id, dst_id_type, data, data_len,
449 /* Send the START_USE indication to remote connection. If `failure' is
450 TRUE then this sends SILC_PACKET_FAILURE. Otherwise it sends
451 SILC_PACKET_RESUME_ROUTER. */
453 void silc_server_backup_send_start_use(SilcServer server,
454 SilcSocketConnection sock,
457 unsigned char data[4];
459 SILC_LOG_DEBUG(("Sending START_USE (%s) to %s",
460 failure ? "failure" : "success", sock->ip));
463 SILC_PUT32_MSB(SILC_SERVER_BACKUP_START_USE, data);
464 silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
467 data[0] = SILC_SERVER_BACKUP_START_USE;
469 silc_server_packet_send(server, sock,
470 SILC_PACKET_RESUME_ROUTER, 0,
475 /* Send the REPLACED indication to remote router. This is send by the
476 primary router (remote router) of the primary router that came back
477 online. This is not sent by backup router or any other server. */
479 void silc_server_backup_send_replaced(SilcServer server,
480 SilcSocketConnection sock)
482 unsigned char data[4];
484 SILC_LOG_DEBUG(("Sending REPLACED (%s) to %s", sock->ip));
486 data[0] = SILC_SERVER_BACKUP_REPLACED;
488 silc_server_packet_send(server, sock,
489 SILC_PACKET_RESUME_ROUTER, 0,
494 /************************ Backup Resuming Protocol **************************/
496 /* Timeout callback for protocol */
498 SILC_TASK_CALLBACK(silc_server_backup_timeout)
500 SilcProtocol protocol = context;
501 SilcServerBackupProtocolContext ctx = protocol->context;
502 SilcServer server = app_context;
504 SILC_LOG_INFO(("Timeout occurred during backup resuming protocol"));
506 silc_protocol_cancel(protocol, server->schedule);
507 protocol->state = SILC_PROTOCOL_STATE_ERROR;
508 silc_protocol_execute_final(protocol, server->schedule);
511 /* Callback to start the protocol as responder */
513 SILC_TASK_CALLBACK(silc_server_backup_responder_start)
515 SilcServerBackupProtocolContext proto_ctx = context;
516 SilcSocketConnection sock = proto_ctx->sock;
517 SilcServer server = app_context;
519 /* If other protocol is executing at the same time, start with timeout. */
520 if (sock->protocol) {
521 SILC_LOG_DEBUG(("Other protocol is executing, wait for it to finish"));
522 silc_schedule_task_add(server->schedule, sock->sock,
523 silc_server_backup_responder_start,
525 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
529 /* Run the backup resuming protocol */
530 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
531 &sock->protocol, proto_ctx,
532 silc_server_protocol_backup_done);
533 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
534 silc_schedule_task_add(server->schedule, sock->sock,
535 silc_server_backup_timeout,
536 sock->protocol, 30, 0, SILC_TASK_TIMEOUT,
537 SILC_TASK_PRI_NORMAL);
540 /* Callback to send START_USE to backup to check whether using backup
543 SILC_TASK_CALLBACK(silc_server_backup_check_status)
545 SilcSocketConnection sock = context;
546 SilcServer server = app_context;
548 /* Check whether we are still using backup */
549 if (!server->backup_primary)
552 silc_server_backup_send_start_use(server, sock, FALSE);
553 silc_socket_free(sock); /* unref */
558 SilcSocketConnection sock;
559 SilcPacketContext *packet;
560 } *SilcServerBackupPing;
562 /* PING command reply callback */
564 void silc_server_backup_ping_reply(void *context, void *reply)
566 SilcServerBackupPing pc = context;
567 SilcServerCommandReplyContext cmdr = reply;
569 if (cmdr && !silc_command_get_status(cmdr->payload, NULL, NULL)) {
570 /* Timeout error occurred, the primary is really down. */
571 SilcSocketConnection primary = SILC_PRIMARY_ROUTE(pc->server);
573 SILC_LOG_DEBUG(("PING timeout, primary is down"));
576 if (primary->user_data)
577 silc_server_free_sock_user_data(pc->server, primary, NULL);
578 SILC_SET_DISCONNECTING(primary);
579 silc_server_close_connection(pc->server, primary);
582 /* Reprocess the RESUME_ROUTER packet */
583 silc_server_backup_resume_router(pc->server, pc->sock, pc->packet);
585 /* The primary is not down, refuse to serve the server as primary */
586 SILC_LOG_DEBUG(("PING received, primary is up"));
587 silc_server_backup_send_start_use(pc->server, pc->sock, TRUE);
590 silc_socket_free(pc->sock);
591 silc_packet_context_free(pc->packet);
595 /* Processes incoming RESUME_ROUTER packet. This can give the packet
596 for processing to the protocol handler or allocate new protocol if
597 start command is received. */
599 void silc_server_backup_resume_router(SilcServer server,
600 SilcSocketConnection sock,
601 SilcPacketContext *packet)
603 SilcUInt8 type, session;
604 SilcServerBackupProtocolContext ctx;
605 SilcIDListData idata;
608 SILC_LOG_DEBUG(("Received RESUME_ROUTER packet"));
610 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
611 sock->type == SILC_SOCKET_TYPE_UNKNOWN) {
612 SILC_LOG_DEBUG(("Bad packet received"));
616 idata = (SilcIDListData)sock->user_data;
618 ret = silc_buffer_unformat(packet->buffer,
619 SILC_STR_UI_CHAR(&type),
620 SILC_STR_UI_CHAR(&session),
623 SILC_LOG_ERROR(("Malformed resume router packet received"));
627 /* Check whether this packet is used to tell us that server will start
628 using us as primary router. */
629 if (type == SILC_SERVER_BACKUP_START_USE) {
631 SilcServerBackupPing pc;
633 /* If we are normal server then backup router has sent us back
634 this reply and we use the backup as primary router now. */
635 if (server->server_type == SILC_SERVER) {
636 /* Nothing to do here actually, since we have switched already. */
637 SILC_LOG_DEBUG(("Received successful START_USE from backup router"));
641 /* Backup router following. */
643 /* If we are marked as router then the primary is down and we send
644 success START_USE back to the server. */
645 if (server->server_type == SILC_ROUTER) {
646 SILC_LOG_DEBUG(("Sending success START_USE back to %s", sock->ip));
647 silc_server_backup_send_start_use(server, sock, FALSE);
651 /* We have just lost primary, send success START_USE back */
652 if (server->standalone) {
653 SILC_LOG_DEBUG(("We are stanalone, sending success START_USE back to %s",
655 silc_server_backup_send_start_use(server, sock, FALSE);
659 /* We are backup router. This server claims that our primary is down.
660 We will check this ourselves by sending PING command to the primary. */
661 SILC_LOG_DEBUG(("Sending PING to detect status of primary router"));
662 idp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER);
663 silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
664 SILC_COMMAND_PING, ++server->cmd_ident, 1,
665 1, idp->data, idp->len);
666 silc_buffer_free(idp);
668 /* Reprocess this packet after received reply from router */
669 pc = silc_calloc(1, sizeof(*pc));
671 pc->sock = silc_socket_dup(sock);
672 pc->packet = silc_packet_context_dup(packet);
673 silc_server_command_pending_timed(server, SILC_COMMAND_PING,
675 silc_server_backup_ping_reply, pc, 15);
680 /* Start the resuming protocol if requested. */
681 if (type == SILC_SERVER_BACKUP_START) {
682 /* We have received a start for resuming protocol. We are either
683 primary router that came back online or normal server. */
684 SilcServerBackupProtocolContext proto_ctx;
686 /* If backup had closed the connection earlier we won't allow resuming
687 since we (primary router) have never gone away. */
688 if (server->server_type == SILC_ROUTER && !server->backup_router &&
689 server->backup_closed) {
690 unsigned char data[4];
691 SILC_LOG_DEBUG(("Backup resuming not allowed since we are still "
693 SILC_LOG_INFO(("Backup resuming not allowed since we are still "
695 SILC_PUT32_MSB(SILC_SERVER_BACKUP_START, data);
696 silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
698 server->backup_closed = FALSE;
702 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
703 proto_ctx->server = server;
704 proto_ctx->sock = silc_socket_dup(sock);
705 proto_ctx->responder = TRUE;
706 proto_ctx->type = type;
707 proto_ctx->session = session;
708 proto_ctx->start = time(0);
710 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
711 SILC_LOG_INFO(("Starting backup resuming protocol"));
713 /* Start protocol immediately */
714 silc_schedule_task_add(server->schedule, sock->sock,
715 silc_server_backup_responder_start,
717 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
722 /* If we are router and the packet is coming from our primary router
723 then it means we have been replaced by an backup router in our cell. */
724 if (type == SILC_SERVER_BACKUP_REPLACED &&
725 server->server_type == SILC_ROUTER &&
726 sock->type == SILC_SOCKET_TYPE_ROUTER &&
727 SILC_PRIMARY_ROUTE(server) == sock) {
728 /* We have been replaced by an backup router in our cell. We must
729 mark our primary router connection disabled since we are not allowed
730 to use it at this moment. */
731 SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
732 "wait until backup resuming protocol is executed"));
733 idata->status |= SILC_IDLIST_STATUS_DISABLED;
738 /* Activate the shared protocol context for this socket connection
740 if (type == SILC_SERVER_BACKUP_RESUMED &&
741 sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol &&
742 idata->status & SILC_IDLIST_STATUS_DISABLED) {
743 SilcServerEntry backup_router;
745 if (silc_server_backup_replaced_get(server, ((SilcServerEntry)idata)->id,
747 SilcSocketConnection bsock =
748 (SilcSocketConnection)backup_router->connection;
749 if (bsock->protocol && bsock->protocol->protocol &&
750 bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
751 sock->protocol = bsock->protocol;
752 ctx = sock->protocol->context;
754 silc_socket_free(ctx->sock); /* unref */
755 ctx->sock = silc_socket_dup(sock);
761 /* Call the resuming protocol if the protocol is active. */
762 if (SILC_SERVER_IS_BACKUP(sock)) {
763 ctx = sock->protocol->context;
766 for (i = 0; i < ctx->sessions_count; i++) {
767 if (session == ctx->sessions[i].session) {
768 ctx->session = session;
769 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
774 /* If RESUMED received the session ID is zero, execute the protocol. */
775 if (type == SILC_SERVER_BACKUP_RESUMED) {
776 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
780 SILC_LOG_ERROR(("Unknown backup resuming session %d", session));
785 /* callback for async connection to remote router */
787 SILC_TASK_CALLBACK(silc_server_backup_connection_established)
789 SilcServer server = app_context;
790 SilcServerConnection sconn = (SilcServerConnection)context;
792 int opt = EINVAL, optlen = sizeof(opt);
794 silc_schedule_task_del_by_fd(server->schedule, sock);
795 silc_schedule_unset_listen_fd(server->schedule, sock);
797 if (silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen) ||
799 SILC_LOG_DEBUG(("Could not connect to router %s:%d: %s", sconn->remote_host,
800 sconn->remote_port, strerror(opt)));
802 if (server->server_type == SILC_SERVER) {
803 sconn->retry_count++;
804 if (sconn->retry_count > 3) {
805 silc_free(sconn->remote_host);
810 silc_schedule_task_add(server->schedule, 0,
811 silc_server_backup_connect_to_router,
812 context, 10, 0, SILC_TASK_TIMEOUT,
813 SILC_TASK_PRI_NORMAL);
817 SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
818 sconn->remote_port));
820 /* Continue with key exchange protocol */
821 silc_server_start_key_exchange(server, sconn, sock);
825 /* Timeout task callback to connect to remote router */
827 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
829 SilcServer server = app_context;
830 SilcServerConnection sconn = (SilcServerConnection)context;
832 const char *server_ip;
834 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
835 sconn->remote_port));
837 /* Connect to remote host */
838 server_ip = server->config->server_info->primary == NULL ? NULL :
839 server->config->server_info->primary->server_ip;
840 sock = silc_net_create_connection_async(server_ip, sconn->remote_port,
843 if (server->server_type == SILC_SERVER) {
844 sconn->retry_count++;
845 if (sconn->retry_count > 3) {
846 silc_free(sconn->remote_host);
851 silc_schedule_task_add(server->schedule, 0,
852 silc_server_backup_connect_to_router,
853 context, 10, 0, SILC_TASK_TIMEOUT,
854 SILC_TASK_PRI_NORMAL);
858 /* wait for the connection to be established */
859 silc_schedule_task_add(server->schedule, sock,
860 silc_server_backup_connection_established,
861 context, 0, 0, SILC_TASK_FD,
862 SILC_TASK_PRI_NORMAL);
863 silc_schedule_set_listen_fd(server->schedule, sock,
864 SILC_TASK_WRITE, FALSE);
867 /* Constantly tries to reconnect to a primary router indicated by the
868 `ip' and `port'. The `connected' callback will be called when the
869 connection is created. */
871 void silc_server_backup_reconnect(SilcServer server,
872 const char *ip, SilcUInt16 port,
873 SilcServerConnectRouterCallback callback,
876 SilcServerConnection sconn;
878 SILC_LOG_INFO(("Attempting to reconnect to primary router"));
880 sconn = silc_calloc(1, sizeof(*sconn));
881 sconn->remote_host = strdup(ip);
882 sconn->remote_port = port;
883 sconn->callback = callback;
884 sconn->callback_context = context;
885 sconn->no_reconnect = TRUE;
886 sconn->retry_count = 0;
887 silc_schedule_task_add(server->schedule, 0,
888 silc_server_backup_connect_to_router,
889 sconn, 1, 0, SILC_TASK_TIMEOUT,
890 SILC_TASK_PRI_NORMAL);
893 /* Task that is called after backup router has connected back to
894 primary router and we are starting the resuming protocol */
896 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
898 SilcServerBackupProtocolContext proto_ctx =
899 (SilcServerBackupProtocolContext)context;
900 SilcServer server = proto_ctx->server;
901 SilcSocketConnection sock = proto_ctx->sock;
903 /* If running other protocol already run this one a bit later. */
904 if (sock->protocol) {
905 SILC_LOG_DEBUG(("Other protocol is running, wait for it to finish"));
906 silc_schedule_task_add(server->schedule, 0,
907 silc_server_backup_connected_later,
910 SILC_TASK_PRI_NORMAL);
914 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
915 SILC_LOG_INFO(("Starting backup resuming protocol"));
917 /* Run the backup resuming protocol */
918 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
919 &sock->protocol, proto_ctx,
920 silc_server_protocol_backup_done);
921 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
923 silc_schedule_task_add(server->schedule, sock->sock,
924 silc_server_backup_timeout,
925 sock->protocol, 30, 0, SILC_TASK_TIMEOUT,
926 SILC_TASK_PRI_NORMAL);
929 /* Called when we've established connection back to our primary router
930 when we've acting as backup router and have replaced the primary router
931 in the cell. This function will start the backup resuming protocol. */
933 void silc_server_backup_connected(SilcServer server,
934 SilcServerEntry server_entry,
937 SilcServerBackupProtocolContext proto_ctx;
938 SilcSocketConnection sock;
942 SilcServerConfigRouter *primary;
943 primary = silc_server_config_get_primary_router(server);
945 if (!silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
946 primary->host, primary->port))
947 silc_server_backup_reconnect(server,
948 primary->host, primary->port,
949 silc_server_backup_connected,
955 sock = (SilcSocketConnection)server_entry->connection;
956 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
957 proto_ctx->server = server;
958 proto_ctx->sock = silc_socket_dup(sock);
959 proto_ctx->responder = FALSE;
960 proto_ctx->type = SILC_SERVER_BACKUP_START;
961 proto_ctx->start = time(0);
963 /* Start through scheduler */
964 silc_schedule_task_add(server->schedule, 0,
965 silc_server_backup_connected_later,
968 SILC_TASK_PRI_NORMAL);
971 /* Called when normal server has connected to its primary router after
972 backup router has sent the START packet in reusming protocol. We will
973 move the protocol context from the backup router connection to the
976 static void silc_server_backup_connect_primary(SilcServer server,
977 SilcServerEntry server_entry,
980 SilcSocketConnection backup_router = (SilcSocketConnection)context;
981 SilcServerBackupProtocolContext ctx;
982 SilcSocketConnection sock;
983 SilcIDListData idata;
984 unsigned char data[2];
986 if (SILC_IS_DISCONNECTING(backup_router) ||
987 SILC_IS_DISCONNECTED(backup_router)) {
988 silc_socket_free(backup_router);
994 SilcServerConfigRouter *primary;
995 primary = silc_server_config_get_primary_router(server);
997 if (!silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
998 primary->host, primary->port))
999 silc_server_backup_reconnect(server,
1000 primary->host, primary->port,
1001 silc_server_backup_connect_primary,
1007 silc_socket_free(backup_router);
1009 if (!backup_router->protocol)
1011 if (!server_entry->connection)
1014 ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context;
1015 sock = (SilcSocketConnection)server_entry->connection;
1016 idata = (SilcIDListData)server_entry;
1018 SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
1019 SILC_LOG_INFO(("Sending CONNECTED (session %d) to backup router",
1022 /* Send the CONNECTED packet back to the backup router. */
1023 data[0] = SILC_SERVER_BACKUP_CONNECTED;
1024 data[1] = ctx->session;
1025 silc_server_packet_send(server, backup_router,
1026 SILC_PACKET_RESUME_ROUTER, 0, data, 2, FALSE);
1028 /* The primary connection is disabled until it sends the RESUMED packet
1030 idata->status |= SILC_IDLIST_STATUS_DISABLED;
1032 /* Move this protocol context from this backup router connection to
1033 the primary router connection since it will send the subsequent
1034 packets in this protocol. We don't talk with backup router
1036 sock->protocol = backup_router->protocol;
1038 silc_socket_free(ctx->sock); /* unref */
1039 ctx->sock = silc_socket_dup(server_entry->connection);
1040 backup_router->protocol = NULL;
1043 /* Timeout callback used by the backup router to send the ENDING packet
1044 to primary router to indicate that it can now resume as being primary
1045 router. All CONNECTED packets has been received when we reach this. */
1047 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
1049 SilcProtocol protocol = (SilcProtocol)context;
1050 SilcServerBackupProtocolContext ctx = protocol->context;
1051 SilcServer server = ctx->server;
1052 unsigned char data[2];
1055 SILC_LOG_DEBUG(("Start"));
1057 for (i = 0; i < ctx->sessions_count; i++)
1058 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
1059 ctx->session = ctx->sessions[i].session;
1061 /* We've received all the CONNECTED packets and now we'll send the
1062 ENDING packet to the new primary router. */
1063 data[0] = SILC_SERVER_BACKUP_ENDING;
1064 data[1] = ctx->session;
1065 silc_server_packet_send(server, ctx->sock, SILC_PACKET_RESUME_ROUTER, 0,
1066 data, sizeof(data), FALSE);
1068 /* The protocol will go to END state. */
1069 protocol->state = SILC_PROTOCOL_STATE_END;
1072 /* Backup resuming protocol. This protocol is executed when the primary
1073 router wants to resume its position as being primary router. */
1075 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
1077 SilcProtocol protocol = (SilcProtocol)context;
1078 SilcServerBackupProtocolContext ctx = protocol->context;
1079 SilcServer server = ctx->server;
1080 SilcServerEntry server_entry;
1081 SilcSocketConnection sock = NULL;
1082 unsigned char data[2];
1085 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
1086 protocol->state = SILC_PROTOCOL_STATE_START;
1088 switch(protocol->state) {
1089 case SILC_PROTOCOL_STATE_START:
1090 if (ctx->responder == FALSE) {
1092 * Initiator (backup router)
1095 /* Send the START packet to primary router and normal servers. The
1096 packet will indicate to the primary router that it has been replaced
1097 by us. For normal servers it means that we will be resigning as
1098 being primary router shortly. */
1099 for (i = 0; i < server->config->param.connections_max; i++) {
1100 sock = server->sockets[i];
1101 if (!sock || !sock->user_data ||
1102 sock->user_data == server->id_entry ||
1103 (sock->type != SILC_SOCKET_TYPE_ROUTER &&
1104 sock->type != SILC_SOCKET_TYPE_SERVER))
1107 server_entry = sock->user_data;
1108 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1111 ctx->sessions = silc_realloc(ctx->sessions,
1112 sizeof(*ctx->sessions) *
1113 (ctx->sessions_count + 1));
1114 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
1115 ctx->sessions[ctx->sessions_count].connected = FALSE;
1116 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
1118 SILC_LOG_DEBUG(("Sending START to %s (session %d)",
1119 server_entry->server_name, ctx->sessions_count));
1120 SILC_LOG_INFO(("Expecting CONNECTED from %s (session %d)",
1121 server_entry->server_name, ctx->sessions_count));
1123 /* This connection is performing this protocol too now */
1124 sock->protocol = protocol;
1126 data[0] = SILC_SERVER_BACKUP_START;
1127 data[1] = ctx->sessions_count;
1128 silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1129 data, sizeof(data), FALSE);
1130 ctx->sessions_count++;
1133 /* Announce data to the new primary to be. */
1134 silc_server_announce_servers(server, TRUE, 0, ctx->sock);
1135 silc_server_announce_clients(server, 0, ctx->sock);
1136 silc_server_announce_channels(server, 0, ctx->sock);
1142 * Responder (all servers and routers)
1144 SilcServerConfigRouter *primary;
1146 /* We should have received START packet */
1147 if (ctx->type != SILC_SERVER_BACKUP_START) {
1148 SILC_LOG_ERROR(("Bad resume router packet START %d", ctx->type));
1152 /* Connect to the primary router that was down that is now supposed
1153 to be back online. We send the CONNECTED packet after we've
1154 established the connection to the primary router. */
1155 primary = silc_server_config_get_primary_router(server);
1156 if (primary && server->backup_primary &&
1157 !silc_server_num_sockets_by_remote(server,
1158 silc_net_is_ip(primary->host) ?
1159 primary->host : NULL,
1160 silc_net_is_ip(primary->host) ?
1161 NULL : primary->host,
1163 SILC_SOCKET_TYPE_ROUTER)) {
1164 SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
1166 silc_server_backup_reconnect(server,
1167 primary->host, primary->port,
1168 silc_server_backup_connect_primary,
1169 silc_socket_dup(ctx->sock));
1171 /* Nowhere to connect just return the CONNECTED packet */
1172 SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
1174 SILC_LOG_INFO(("Sending CONNECTED (session %d) to backup router",
1177 /* Send the CONNECTED packet back to the backup router. */
1178 data[0] = SILC_SERVER_BACKUP_CONNECTED;
1179 data[1] = ctx->session;
1180 silc_server_packet_send(server, ctx->sock,
1181 SILC_PACKET_RESUME_ROUTER, 0,
1182 data, sizeof(data), FALSE);
1185 /* Add this resuming session */
1186 ctx->sessions = silc_realloc(ctx->sessions,
1187 sizeof(*ctx->sessions) *
1188 (ctx->sessions_count + 1));
1189 ctx->sessions[ctx->sessions_count].session = ctx->session;
1190 ctx->sessions_count++;
1192 /* Normal server goes directly to the END state. */
1193 if (server->server_type == SILC_ROUTER &&
1195 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
1198 protocol->state = SILC_PROTOCOL_STATE_END;
1203 if (ctx->responder == FALSE) {
1205 * Initiator (backup router)
1208 /* We should have received CONNECTED packet */
1209 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
1210 SILC_LOG_ERROR(("Bad resume router packet CONNECTED %d", ctx->type));
1214 for (i = 0; i < ctx->sessions_count; i++) {
1215 if (ctx->sessions[i].session == ctx->session) {
1216 ctx->sessions[i].connected = TRUE;
1217 SILC_LOG_INFO(("Received CONNECTED from %s (session %d)",
1218 ctx->sessions[i].server_entry->server_name,
1220 SILC_LOG_DEBUG(("Received CONNECTED (session %d)", ctx->session));
1225 /* See if all returned CONNECTED, if not, then continue waiting. */
1226 for (i = 0; i < ctx->sessions_count; i++) {
1227 if (!ctx->sessions[i].connected)
1231 SILC_LOG_INFO(("All sessions have returned CONNECTED packets, "
1233 SILC_LOG_DEBUG(("Sending ENDING packet to primary router"));
1235 /* The ENDING is sent with timeout, and then we continue to the
1236 END state in the protocol. */
1237 silc_schedule_task_add(server->schedule, 0,
1238 silc_server_backup_send_resumed,
1239 protocol, 1, 0, SILC_TASK_TIMEOUT,
1240 SILC_TASK_PRI_NORMAL);
1245 * Responder (primary router)
1248 /* We should have been received ENDING packet */
1249 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
1250 SILC_LOG_ERROR(("Bad resume router packet ENDING %d", ctx->type));
1254 SILC_LOG_DEBUG(("Received ENDING packet, we are going to resume now"));
1256 /* Switch announced informations to our primary router of using the
1258 silc_server_local_servers_toggle_enabled(server, TRUE);
1259 silc_server_update_servers_by_server(server, ctx->sock->user_data,
1261 silc_server_update_clients_by_server(server, ctx->sock->user_data,
1262 server->router, TRUE);
1264 /* We as primary router now must send RESUMED packets to all servers
1265 and routers so that they know we are back. For backup router we
1266 send the packet last so that we give the backup as much time as
1267 possible to deal with message routing at this critical moment. */
1268 for (i = 0; i < server->config->param.connections_max; i++) {
1269 sock = server->sockets[i];
1270 if (!sock || !sock->user_data ||
1271 sock->user_data == server->id_entry ||
1272 (sock->type != SILC_SOCKET_TYPE_ROUTER &&
1273 sock->type != SILC_SOCKET_TYPE_SERVER))
1276 /* Send to backup last */
1277 if (sock == ctx->sock)
1281 server_entry = sock->user_data;
1282 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1284 SILC_LOG_DEBUG(("Sending RESUMED to %s", server_entry->server_name));
1285 SILC_LOG_INFO(("Sending RESUMED to %s", server_entry->server_name));
1287 /* This connection is performing this protocol too now */
1288 sock->protocol = protocol;
1290 data[0] = SILC_SERVER_BACKUP_RESUMED;
1292 silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1293 data, sizeof(data), FALSE);
1294 silc_server_packet_queue_purge(server, sock);
1297 /* Now send the same packet to backup */
1298 if (sock != ctx->sock) {
1301 goto send_to_backup;
1304 /* We are now resumed and are back as primary router in the cell. */
1305 SILC_LOG_INFO(("We are now the primary router of our cell again"));
1306 server->wait_backup = FALSE;
1308 /* For us this is the end of this protocol. */
1309 if (protocol->final_callback)
1310 silc_protocol_execute_final(protocol, server->schedule);
1312 silc_protocol_free(protocol);
1316 case SILC_PROTOCOL_STATE_END:
1319 * Responder (backup router, servers, and remote router)
1321 SilcServerEntry router, backup_router;
1323 /* We should have been received RESUMED from our primary router. */
1324 if (ctx->type != SILC_SERVER_BACKUP_RESUMED) {
1325 SILC_LOG_ERROR(("Bad resume router packet RESUMED %d", ctx->type));
1329 SILC_LOG_INFO(("Received RESUMED from new primary router"));
1331 /* If we are the backup router, mark that we are no longer primary
1332 but are back to backup router status. */
1333 if (server->backup_router)
1334 server->server_type = SILC_BACKUP_ROUTER;
1336 /* We have now new primary router. All traffic goes there from now on. */
1337 router = ctx->sock->user_data;
1338 if (silc_server_backup_replaced_get(server, router->id,
1341 if (backup_router == server->router) {
1342 /* We have new primary router now */
1343 server->id_entry->router = router;
1344 server->router = router;
1345 SILC_LOG_INFO(("Switching back to primary router %s",
1346 server->router->server_name));
1348 /* We are connected to new primary and now continue using it */
1349 SILC_LOG_INFO(("Resuming the use of primary router %s",
1350 router->server_name));
1352 server->backup_primary = FALSE;
1353 sock = router->connection;
1355 /* Update the client entries of the backup router to the new
1357 silc_server_local_servers_toggle_enabled(server, FALSE);
1358 router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1359 silc_server_update_servers_by_server(server, backup_router, router);
1360 silc_server_update_clients_by_server(
1361 server, NULL, router,
1362 server->server_type == SILC_BACKUP_ROUTER);
1363 if (server->server_type == SILC_SERVER)
1364 silc_server_update_channels_by_server(server, backup_router, router);
1365 silc_server_backup_replaced_del(server, backup_router);
1368 /* Send notify about primary router going down to local operators */
1369 SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1370 SILC_NOTIFY_TYPE_NONE,
1371 ("%s resumed the use of primary router %s",
1372 server->server_name,
1373 server->router->server_name));
1375 /* Protocol has ended, call the final callback */
1376 if (protocol->final_callback)
1377 silc_protocol_execute_final(protocol, server->schedule);
1379 silc_protocol_free(protocol);
1383 case SILC_PROTOCOL_STATE_ERROR:
1384 /* Protocol has ended, call the final callback */
1385 if (protocol->final_callback)
1386 silc_protocol_execute_final(protocol, server->schedule);
1388 silc_protocol_free(protocol);
1391 case SILC_PROTOCOL_STATE_FAILURE:
1392 /* Protocol has ended, call the final callback */
1393 SILC_LOG_ERROR(("Error during backup resume: received Failure"));
1394 ctx->received_failure = TRUE;
1395 if (protocol->final_callback)
1396 silc_protocol_execute_final(protocol, server->schedule);
1398 silc_protocol_free(protocol);
1401 case SILC_PROTOCOL_STATE_UNKNOWN:
1406 /* Final resuming protocol completion callback */
1408 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1410 SilcProtocol protocol = (SilcProtocol)context;
1411 SilcServerBackupProtocolContext ctx = protocol->context;
1412 SilcServer server = ctx->server;
1413 SilcServerEntry server_entry;
1414 SilcSocketConnection sock;
1418 silc_schedule_task_del_by_context(server->schedule, protocol);
1420 error = (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1421 protocol->state == SILC_PROTOCOL_STATE_FAILURE);
1424 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1425 if (server->server_type == SILC_SERVER)
1426 silc_schedule_task_del_by_callback(server->schedule,
1427 silc_server_backup_connect_to_router);
1430 if (server->server_shutdown)
1433 /* Remove this protocol from all server entries that has it */
1434 for (i = 0; i < server->config->param.connections_max; i++) {
1435 sock = server->sockets[i];
1436 if (!sock || !sock->user_data ||
1437 (sock->type != SILC_SOCKET_TYPE_ROUTER &&
1438 sock->type != SILC_SOCKET_TYPE_SERVER))
1441 server_entry = sock->user_data;
1443 /* The SilcProtocol context was shared between all connections, clear
1444 it from all connections. */
1445 if (sock->protocol == protocol) {
1446 silc_server_packet_queue_purge(server, sock);
1447 sock->protocol = NULL;
1451 if (server->server_type == SILC_SERVER &&
1452 server_entry->server_type == SILC_ROUTER)
1456 if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
1457 if (ctx->sock == sock) {
1458 silc_socket_free(sock); /* unref */
1462 if (!ctx->received_failure) {
1463 /* Protocol error, probably timeout. Just restart the protocol. */
1464 SilcServerBackupProtocolContext proto_ctx;
1466 /* Restart the protocol. */
1467 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1468 proto_ctx->server = server;
1469 proto_ctx->sock = silc_socket_dup(sock);
1470 proto_ctx->responder = FALSE;
1471 proto_ctx->type = SILC_SERVER_BACKUP_START;
1472 proto_ctx->start = time(0);
1474 /* Start through scheduler */
1475 silc_schedule_task_add(server->schedule, 0,
1476 silc_server_backup_connected_later,
1479 SILC_TASK_PRI_NORMAL);
1481 /* If failure was received, switch back to normal backup router.
1482 For some reason primary wouldn't accept that we were supposed
1483 to perfom resuming protocol. */
1484 server->server_type = SILC_BACKUP_ROUTER;
1485 silc_server_local_servers_toggle_enabled(server, FALSE);
1486 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1487 silc_server_update_servers_by_server(server, server->id_entry,
1489 silc_server_update_clients_by_server(server, NULL,
1490 sock->user_data, TRUE);
1492 /* Announce our clients and channels to the router */
1493 silc_server_announce_clients(server, 0, sock);
1494 silc_server_announce_channels(server, 0, sock);
1501 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1506 SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
1508 if (ctx->type == SILC_SERVER_BACKUP_RESUMED && server->router) {
1509 /* Announce all of our information to the router. */
1510 if (server->server_type == SILC_ROUTER)
1511 silc_server_announce_servers(server, FALSE, 0,
1512 server->router->connection);
1514 /* Announce our clients and channels to the router */
1515 silc_server_announce_clients(server, 0, server->router->connection);
1516 silc_server_announce_channels(server, 0, server->router->connection);
1521 if (server->server_type == SILC_SERVER) {
1522 /* If we are still using backup router Send confirmation to backup
1523 that using it is still ok and continue sending traffic there.
1524 The backup will reply with error if it's not ok. */
1525 if (server->router && server->backup_primary) {
1526 /* Send START_USE just in case using backup wouldn't be ok. */
1527 silc_server_backup_send_start_use(server, server->router->connection,
1530 /* Check couple of times same START_USE just in case. */
1531 silc_schedule_task_add(server->schedule, 0,
1532 silc_server_backup_check_status,
1533 silc_socket_dup(server->router->connection),
1534 5, 1, SILC_TASK_TIMEOUT,
1535 SILC_TASK_PRI_NORMAL);
1536 silc_schedule_task_add(server->schedule, 0,
1537 silc_server_backup_check_status,
1538 silc_socket_dup(server->router->connection),
1539 20, 1, SILC_TASK_TIMEOUT,
1540 SILC_TASK_PRI_NORMAL);
1541 silc_schedule_task_add(server->schedule, 0,
1542 silc_server_backup_check_status,
1543 silc_socket_dup(server->router->connection),
1544 60, 1, SILC_TASK_TIMEOUT,
1545 SILC_TASK_PRI_NORMAL);
1550 if (ctx->sock && ctx->sock->protocol)
1551 ctx->sock->protocol = NULL;
1553 silc_socket_free(ctx->sock); /* unref */
1554 silc_protocol_free(protocol);
1555 silc_free(ctx->sessions);