3bde1802a3f00cb405bba34c5fa26c89f50b42f4
[silc.git] / apps / silcd / server_backup.c
1 /*
2
3   server_backup.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 - 2007 Pekka Riikonen
8
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.
12
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.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23
24 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
25 SILC_TASK_CALLBACK(silc_server_backup_announce_watches);
26
27 static void silc_server_backup_connect_primary(SilcServer server,
28                                                SilcServerEntry server_entry,
29                                                void *context);
30
31
32 /************************** Types and Definitions ***************************/
33
34 /* Backup router */
35 typedef struct {
36   SilcServerEntry server;
37   SilcIDIP ip;
38   SilcUInt16 port;
39   SilcBool local;
40 } SilcServerBackupEntry;
41
42 /* Holds IP address and port of the primary router that was replaced
43    by backup router. */
44 typedef struct {
45   SilcIDIP ip;
46   SilcUInt16 port;
47   SilcServerEntry server;       /* Backup router that replaced the primary */
48 } SilcServerBackupReplaced;
49
50 /* Backup context */
51 struct SilcServerBackupStruct {
52   SilcServerBackupEntry *servers;
53   SilcUInt32 servers_count;
54   SilcServerBackupReplaced **replaced;
55   SilcUInt32 replaced_count;
56 };
57
58 typedef struct {
59   SilcUInt8 session;
60   SilcBool connected;
61   SilcServerEntry server_entry;
62 } SilcServerBackupProtocolSession;
63
64 /* Backup resuming protocol context  */
65 typedef struct {
66   SilcServer server;
67   SilcPacketStream sock;
68   SilcUInt8 type;
69   SilcUInt8 session;
70   SilcServerBackupProtocolSession *sessions;
71   SilcUInt32 sessions_count;
72   SilcUInt32 initiator_restart;
73   long start;
74   int state;
75   unsigned int responder        : 1;
76   unsigned int received_failure : 1;
77   unsigned int timeout          : 1;
78   unsigned int error            : 1;
79 } *SilcServerBackupProtocolContext;
80
81
82 /********************* Backup Configuration Routines ************************/
83
84 /* Adds the `backup_server' to be one of our backup router. This can be
85    called multiple times to set multiple backup routers. The `ip' and `port'
86    is the IP and port that the `backup_router' will replace if the `ip'
87    will become unresponsive. If `local' is TRUE then the `backup_server' is
88    in the local cell, if FALSE it is in some other cell. */
89
90 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
91                             const char *ip, int port, SilcBool local)
92 {
93   int i;
94
95   if (!ip)
96     return;
97
98   if (!server->backup) {
99     server->backup = silc_calloc(1, sizeof(*server->backup));
100     if (!server->backup)
101       return;
102   }
103
104   /* See if already added */
105   for (i = 0; i < server->backup->servers_count; i++) {
106     if (server->backup->servers[i].server == backup_server)
107       return;
108   }
109
110   SILC_LOG_DEBUG(("Backup router %s will replace %s",
111                   backup_server->data.sconn ?
112                   backup_server->data.sconn->remote_host : "(me)", ip));
113
114   for (i = 0; i < server->backup->servers_count; i++) {
115     if (!server->backup->servers[i].server) {
116       server->backup->servers[i].server = backup_server;
117       server->backup->servers[i].local = local;
118       server->backup->servers[i].port = SILC_SWAB_16(port);
119       memset(server->backup->servers[i].ip.data, 0,
120              sizeof(server->backup->servers[i].ip.data));
121       silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
122                         sizeof(server->backup->servers[i].ip.data));
123       return;
124     }
125   }
126
127   i = server->backup->servers_count;
128   server->backup->servers = silc_realloc(server->backup->servers,
129                                          sizeof(*server->backup->servers) *
130                                          (i + 1));
131   server->backup->servers[i].server = backup_server;
132   server->backup->servers[i].local = local;
133   server->backup->servers[i].port = SILC_SWAB_16(port);
134   memset(server->backup->servers[i].ip.data, 0,
135          sizeof(server->backup->servers[i].ip.data));
136   silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
137                     sizeof(server->backup->servers[i].ip.data));
138   server->backup->servers_count++;
139 }
140
141 /* Returns backup router for IP and port in `server_id' or NULL if there
142    does not exist backup router. */
143
144 SilcServerEntry silc_server_backup_get(SilcServer server,
145                                        SilcServerID *server_id)
146 {
147   int i;
148
149   if (!server->backup)
150     return NULL;
151
152   for (i = 0; i < server->backup->servers_count; i++) {
153     if (server->backup->servers[i].server &&
154         server->backup->servers[i].port == server_id->port &&
155         !memcmp(server->backup->servers[i].ip.data, server_id->ip.data,
156                 sizeof(server_id->ip.data))) {
157       SILC_LOG_DEBUG(("Found backup router %s for %s",
158                       server->backup->servers[i].server->server_name,
159                       silc_id_render(server_id, SILC_ID_SERVER)));
160       return server->backup->servers[i].server;
161     }
162   }
163
164   return NULL;
165 }
166
167 /* Deletes the backup server `server_entry'. */
168
169 void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry)
170 {
171   int i;
172
173   if (!server->backup)
174     return;
175
176   for (i = 0; i < server->backup->servers_count; i++) {
177     if (server->backup->servers[i].server == server_entry) {
178       SILC_LOG_DEBUG(("Removing %s as backup router",
179                       silc_id_render(server->backup->servers[i].server->id,
180                                      SILC_ID_SERVER)));
181       server->backup->servers[i].server = NULL;
182       memset(server->backup->servers[i].ip.data, 0,
183              sizeof(server->backup->servers[i].ip.data));
184     }
185   }
186 }
187
188 /* Frees all data allocated for backup routers.  Call this after deleting
189    all backup routers and when new routers are added no more, for example
190    when shutting down the server. */
191
192 void silc_server_backup_free(SilcServer server)
193 {
194   int i;
195
196   if (!server->backup)
197     return;
198
199   /* Delete existing servers if caller didn't do it */
200   for (i = 0; i < server->backup->servers_count; i++) {
201     if (server->backup->servers[i].server)
202       silc_server_backup_del(server, server->backup->servers[i].server);
203   }
204
205   silc_free(server->backup->servers);
206   silc_free(server->backup);
207   server->backup = NULL;
208 }
209
210 /* Marks the IP address and port from the `server_id' as  being replaced
211    by backup router indicated by the `server'. If the router connects at
212    a later time we can check whether it has been replaced by an backup
213    router. */
214
215 void silc_server_backup_replaced_add(SilcServer server,
216                                      SilcServerID *server_id,
217                                      SilcServerEntry server_entry)
218 {
219   int i;
220   SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
221
222   if (!server->backup)
223     server->backup = silc_calloc(1, sizeof(*server->backup));
224   if (!server->backup->replaced) {
225     server->backup->replaced =
226       silc_calloc(1, sizeof(*server->backup->replaced));
227     server->backup->replaced_count = 1;
228   }
229
230   SILC_LOG_DEBUG(("Replacing router %s with %s",
231                   silc_id_render(server_id, SILC_ID_SERVER),
232                   server_entry->server_name));
233
234   memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
235   r->server = server_entry;
236
237   for (i = 0; i < server->backup->replaced_count; i++) {
238     if (!server->backup->replaced[i]) {
239       server->backup->replaced[i] = r;
240       return;
241     }
242   }
243
244   i = server->backup->replaced_count;
245   server->backup->replaced = silc_realloc(server->backup->replaced,
246                                           sizeof(*server->backup->replaced) *
247                                           (i + 1));
248   server->backup->replaced[i] = r;
249   server->backup->replaced_count++;
250 }
251
252 /* Checks whether the IP address and port from the `server_id' has been
253    replaced by an backup router. If it has been then this returns TRUE
254    and the bacup router entry to the `server' pointer if non-NULL. Returns
255    FALSE if the router is not replaced by backup router. */
256
257 SilcBool silc_server_backup_replaced_get(SilcServer server,
258                                          SilcServerID *server_id,
259                                          SilcServerEntry *server_entry)
260 {
261   int i;
262
263   if (!server->backup || !server->backup->replaced)
264     return FALSE;
265
266   for (i = 0; i < server->backup->replaced_count; i++) {
267     if (!server->backup->replaced[i])
268       continue;
269     if (!memcmp(server->backup->replaced[i]->ip.data, server_id->ip.data,
270                 sizeof(server_id->ip.data))) {
271       if (server_entry)
272         *server_entry = server->backup->replaced[i]->server;
273       SILC_LOG_DEBUG(("Router %s is replaced by %s",
274                       silc_id_render(server_id, SILC_ID_SERVER),
275                       server->backup->replaced[i]->server->server_name));
276       return TRUE;
277     }
278   }
279
280   SILC_LOG_DEBUG(("Router %s is not replaced by backup router",
281                   silc_id_render(server_id, SILC_ID_SERVER)));
282   return FALSE;
283 }
284
285 /* Deletes a replaced host by the set `server_entry. */
286
287 void silc_server_backup_replaced_del(SilcServer server,
288                                      SilcServerEntry server_entry)
289 {
290   int i;
291
292   if (!server->backup || !server->backup->replaced)
293     return;
294
295   for (i = 0; i < server->backup->replaced_count; i++) {
296     if (!server->backup->replaced[i])
297       continue;
298     if (server->backup->replaced[i]->server == server_entry) {
299       silc_free(server->backup->replaced[i]);
300       server->backup->replaced[i] = NULL;
301     }
302   }
303 }
304
305 /* Broadcast the received packet indicated by `packet' to all of our backup
306    routers. All router wide information is passed using broadcast packets.
307    That is why all backup routers need to get this data too. It is expected
308    that the caller already knows that the `packet' is broadcast packet. */
309
310 void silc_server_backup_broadcast(SilcServer server,
311                                   SilcPacketStream sender,
312                                   SilcPacket packet)
313 {
314   SilcServerEntry backup;
315   SilcPacketStream sock;
316   int i;
317
318   if (!server->backup || server->server_type != SILC_ROUTER)
319     return;
320
321   SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
322
323   for (i = 0; i < server->backup->servers_count; i++) {
324     backup = server->backup->servers[i].server;
325
326     if (!backup || backup->connection == sender ||
327         server->backup->servers[i].local == FALSE)
328       continue;
329     if (server->backup->servers[i].server == server->id_entry)
330       continue;
331
332     sock = backup->connection;
333     silc_server_packet_route(server, sock, packet);
334   }
335 }
336
337 /* A generic routine to send data to all backup routers. If the `sender'
338    is provided it will indicate the original sender of the packet and the
339    packet won't be resent to that entity. The `data' is the data that will
340    be assembled to packet context before sending. The packet will be
341    encrypted this function. If the `force_send' is TRUE the data is sent
342    immediately and not put to queue. If `local' is TRUE then the packet
343    will be sent only to local backup routers inside the cell. If false the
344    packet can go from one cell to the other. This function has no effect
345    if there are no any backup routers. */
346
347 void silc_server_backup_send(SilcServer server,
348                              SilcServerEntry sender,
349                              SilcPacketType type,
350                              SilcPacketFlags flags,
351                              unsigned char *data,
352                              SilcUInt32 data_len,
353                              SilcBool force_send,
354                              SilcBool local)
355 {
356   SilcServerEntry backup;
357   SilcPacketStream sock;
358   int i;
359
360   if (!server->backup || server->server_type != SILC_ROUTER)
361     return;
362
363   for (i = 0; i < server->backup->servers_count; i++) {
364     backup = server->backup->servers[i].server;
365     if (!backup || sender == backup)
366       continue;
367     if (local && server->backup->servers[i].local == FALSE)
368       continue;
369     if (server->backup->servers[i].server == server->id_entry)
370       continue;
371
372     sock = backup->connection;
373
374     silc_server_packet_send(server, backup->connection, type, flags,
375                             data, data_len);
376   }
377 }
378
379 /* Same as silc_server_backup_send but sets a specific Destination ID to
380    the packet. The Destination ID is indicated by the `dst_id' and the
381    ID type `dst_id_type'. For example, packets destined to channels must
382    be sent using this function. */
383
384 void silc_server_backup_send_dest(SilcServer server,
385                                   SilcServerEntry sender,
386                                   SilcPacketType type,
387                                   SilcPacketFlags flags,
388                                   void *dst_id,
389                                   SilcIdType dst_id_type,
390                                   unsigned char *data,
391                                   SilcUInt32 data_len,
392                                   SilcBool force_send,
393                                   SilcBool local)
394 {
395   SilcServerEntry backup;
396   SilcPacketStream sock;
397   int i;
398
399   if (!server->backup || server->server_type != SILC_ROUTER)
400     return;
401
402   for (i = 0; i < server->backup->servers_count; i++) {
403     backup = server->backup->servers[i].server;
404     if (!backup || sender == backup)
405       continue;
406     if (local && server->backup->servers[i].local == FALSE)
407       continue;
408     if (server->backup->servers[i].server == server->id_entry)
409       continue;
410
411     sock = backup->connection;
412
413     silc_server_packet_send_dest(server, backup->connection, type, flags,
414                                  dst_id, dst_id_type, data, data_len);
415   }
416 }
417
418 /* Send the START_USE indication to remote connection.  If `failure' is
419    TRUE then this sends SILC_PACKET_FAILURE.  Otherwise it sends
420    SILC_PACKET_RESUME_ROUTER. */
421
422 void silc_server_backup_send_start_use(SilcServer server,
423                                        SilcPacketStream sock,
424                                        SilcBool failure)
425 {
426   unsigned char data[4];
427
428   SILC_LOG_DEBUG(("Sending START_USE (%s)",
429                   failure ? "failure" : "success"));
430
431   if (failure) {
432     SILC_PUT32_MSB(SILC_SERVER_BACKUP_START_USE, data);
433     silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
434                             data, 4);
435   } else {
436     data[0] = SILC_SERVER_BACKUP_START_USE;
437     data[1] = 0;
438     silc_server_packet_send(server, sock,
439                             SILC_PACKET_RESUME_ROUTER, 0,
440                             data, 2);
441   }
442 }
443
444 /* Send the REPLACED indication to remote router.  This is send by the
445    primary router (remote router) of the primary router that came back
446    online.  This is not sent by backup router or any other server. */
447
448 void silc_server_backup_send_replaced(SilcServer server,
449                                       SilcPacketStream sock)
450 {
451   unsigned char data[4];
452
453   SILC_LOG_DEBUG(("Sending REPLACED"));
454
455   data[0] = SILC_SERVER_BACKUP_REPLACED;
456   data[1] = 0;
457   silc_server_packet_send(server, sock,
458                           SILC_PACKET_RESUME_ROUTER, 0,
459                           data, 2);
460 }
461
462
463 /************************ Backup Resuming Protocol **************************/
464
465 /* Timeout callback for protocol */
466
467 SILC_TASK_CALLBACK(silc_server_backup_timeout)
468 {
469   SilcServerBackupProtocolContext ctx = context;
470   SilcServer server = app_context;
471
472   SILC_LOG_INFO(("Timeout occurred during backup resuming protocol"));
473   ctx->timeout = TRUE;
474   ctx->error = TRUE;
475   silc_schedule_task_add_timeout(server->schedule,
476                                  silc_server_protocol_backup_done, context,
477                                  0, 0);
478 }
479
480 /* Callback to start the protocol as responder */
481
482 SILC_TASK_CALLBACK(silc_server_backup_responder_start)
483 {
484   SilcServerBackupProtocolContext proto_ctx = context;
485   SilcPacketStream sock = proto_ctx->sock;
486   SilcIDListData idata = silc_packet_get_context(sock);
487   SilcServer server = app_context;
488
489   /* If other protocol is executing at the same time, start with timeout. */
490   if (idata->sconn->op) {
491     SILC_LOG_DEBUG(("Other protocol is executing, wait for it to finish"));
492     silc_schedule_task_add_timeout(server->schedule,
493                                    silc_server_backup_responder_start,
494                                    proto_ctx, 2, 0);
495     return;
496   }
497
498   /* Register protocol timeout */
499   silc_schedule_task_add_timeout(server->schedule,
500                                  silc_server_backup_timeout,
501                                  proto_ctx, 30, 0);
502
503   /* Run the backup resuming protocol */
504   silc_schedule_task_add_timeout(server->schedule,
505                                  silc_server_protocol_backup,
506                                  proto_ctx, 0, 0);
507 }
508
509 /* Callback to send START_USE to backup to check whether using backup
510    is ok. */
511
512 SILC_TASK_CALLBACK(silc_server_backup_check_status)
513 {
514   SilcPacketStream sock = context;
515   SilcServer server = app_context;
516
517   /* Check whether we are still using backup */
518   if (!server->backup_primary)
519     return;
520
521   silc_server_backup_send_start_use(server, sock, FALSE);
522   silc_packet_stream_unref(sock);
523 }
524
525 typedef struct {
526   SilcServer server;
527   SilcPacketStream sock;
528   SilcPacket packet;
529 } *SilcServerBackupPing;
530
531 /* PING command reply callback */
532
533 void silc_server_backup_ping_reply(void *context, void *reply)
534 {
535   SilcServerBackupPing pc = context;
536   SilcServerCommandReplyContext cmdr = reply;
537
538   if (cmdr && !silc_command_get_status(cmdr->payload, NULL, NULL)) {
539     /* Timeout error occurred, the primary is really down. */
540     SilcPacketStream primary = SILC_PRIMARY_ROUTE(pc->server);
541
542     SILC_LOG_DEBUG(("PING timeout, primary is down"));
543
544     if (primary) {
545       silc_server_free_sock_user_data(pc->server, primary, NULL);
546       silc_server_close_connection(pc->server, primary);
547     }
548
549     /* Reprocess the RESUME_ROUTER packet */
550     silc_server_backup_resume_router(pc->server, pc->sock, pc->packet);
551   } else {
552     /* The primary is not down, refuse to serve the server as primary */
553     SILC_LOG_DEBUG(("PING received, primary is up"));
554     silc_server_backup_send_start_use(pc->server, pc->sock, TRUE);
555     silc_packet_free(pc->packet);
556   }
557
558   silc_packet_stream_unref(pc->sock);
559   silc_free(pc);
560 }
561
562 /* Processes incoming RESUME_ROUTER packet. This can give the packet
563    for processing to the protocol handler or allocate new protocol if
564    start command is received. */
565
566 void silc_server_backup_resume_router(SilcServer server,
567                                       SilcPacketStream sock,
568                                       SilcPacket packet)
569 {
570   SilcIDListData idata = silc_packet_get_context(sock);
571   SilcServerEntry router = (SilcServerEntry)idata;
572   SilcUInt8 type, session;
573   SilcServerBackupProtocolContext ctx;
574   int i, ret;
575
576   SILC_LOG_DEBUG(("Received RESUME_ROUTER packet"));
577
578   if (idata->conn_type == SILC_CONN_CLIENT ||
579       idata->conn_type == SILC_CONN_UNKNOWN) {
580     SILC_LOG_DEBUG(("Bad packet received"));
581     silc_packet_free(packet);
582     return;
583   }
584
585   ret = silc_buffer_unformat(&packet->buffer,
586                              SILC_STR_UI_CHAR(&type),
587                              SILC_STR_UI_CHAR(&session),
588                              SILC_STR_END);
589   if (ret < 0) {
590     SILC_LOG_ERROR(("Malformed resume router packet received"));
591     silc_packet_free(packet);
592     return;
593   }
594
595   /* Check whether this packet is used to tell us that server will start
596      using us as primary router. */
597   if (type == SILC_SERVER_BACKUP_START_USE) {
598     SilcBuffer idp;
599     SilcServerBackupPing pc;
600
601     /* If we are normal server then backup router has sent us back
602        this reply and we use the backup as primary router now. */
603     if (server->server_type == SILC_SERVER) {
604       /* Nothing to do here actually, since we have switched already. */
605       SILC_LOG_DEBUG(("Received successful START_USE from backup router"));
606       silc_packet_free(packet);
607       return;
608     }
609
610     /* Backup router following. */
611
612     /* If we are marked as router then the primary is down and we send
613        success START_USE back to the server. */
614     if (server->server_type == SILC_ROUTER) {
615       SILC_LOG_DEBUG(("Sending success START_USE back"));
616       silc_server_backup_send_start_use(server, sock, FALSE);
617       silc_packet_free(packet);
618       return;
619     }
620
621     /* We have just lost primary, send success START_USE back */
622     if (server->standalone) {
623       SILC_LOG_DEBUG(("We are stanalone, sending success START_USE back"));
624       silc_server_backup_send_start_use(server, sock, FALSE);
625       silc_packet_free(packet);
626       return;
627     }
628
629     /* We are backup router. This server claims that our primary is down.
630        We will check this ourselves by sending PING command to the primary. */
631     SILC_LOG_DEBUG(("Sending PING to detect status of primary router"));
632     idp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER);
633     silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
634                              SILC_COMMAND_PING, ++server->cmd_ident, 1,
635                              1, idp->data, silc_buffer_len(idp));
636     silc_buffer_free(idp);
637
638     /* Reprocess this packet after received reply from router */
639     pc = silc_calloc(1, sizeof(*pc));
640     pc->server = server;
641     pc->sock = sock;
642     pc->packet = packet;
643     silc_packet_stream_ref(sock);
644     silc_server_command_pending_timed(server, SILC_COMMAND_PING,
645                                       server->cmd_ident,
646                                       silc_server_backup_ping_reply, pc, 15);
647     return;
648   }
649
650   /* Start the resuming protocol if requested. */
651   if (type == SILC_SERVER_BACKUP_START) {
652     /* We have received a start for resuming protocol.  We are either
653        primary router that came back online or normal server. */
654     SilcServerBackupProtocolContext proto_ctx;
655
656     /* If backup had closed the connection earlier we won't allow resuming
657        since we (primary router) have never gone away. */
658     if (server->server_type == SILC_ROUTER && !server->backup_router &&
659         server->backup_closed) {
660       unsigned char data[4];
661       SILC_LOG_DEBUG(("Backup resuming not allowed since we are still "
662                       "primary router"));
663       SILC_LOG_INFO(("Backup resuming not allowed since we are still "
664                      "primary router"));
665       SILC_PUT32_MSB(SILC_SERVER_BACKUP_START, data);
666       silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
667                               data, 4);
668       server->backup_closed = FALSE;
669       silc_packet_free(packet);
670       return;
671     }
672
673     proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
674     proto_ctx->server = server;
675     proto_ctx->sock = sock;
676     proto_ctx->responder = TRUE;
677     proto_ctx->type = type;
678     proto_ctx->session = session;
679     proto_ctx->start = time(0);
680     silc_packet_stream_ref(sock);
681     router->backup = TRUE;
682     router->backup_proto = proto_ctx;
683
684     SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
685     SILC_LOG_INFO(("Starting backup resuming protocol"));
686
687     /* Start protocol immediately */
688     silc_schedule_task_add_timeout(server->schedule,
689                                    silc_server_backup_responder_start,
690                                    proto_ctx, 0, 1);
691     return;
692   }
693
694   /* If we are router and the packet is coming from our primary router
695      then it means we have been replaced by an backup router in our cell. */
696   if (type == SILC_SERVER_BACKUP_REPLACED &&
697       server->server_type == SILC_ROUTER &&
698       idata->conn_type == SILC_CONN_ROUTER &&
699       SILC_PRIMARY_ROUTE(server) == sock) {
700     /* We have been replaced by an backup router in our cell. We must
701        mark our primary router connection disabled since we are not allowed
702        to use it at this moment. */
703     SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
704                    "wait until backup resuming protocol is executed"));
705     idata->status |= SILC_IDLIST_STATUS_DISABLED;
706     silc_packet_free(packet);
707     return;
708   }
709
710   /* Activate the shared protocol context for this socket connection
711      if necessary */
712   if (type == SILC_SERVER_BACKUP_RESUMED &&
713       idata->conn_type == SILC_CONN_ROUTER && !router->backup &&
714       idata->status & SILC_IDLIST_STATUS_DISABLED) {
715     SilcServerEntry backup_router;
716
717     if (silc_server_backup_replaced_get(server, router->id, &backup_router)) {
718       ctx = backup_router->backup_proto;
719       if (ctx->sock)
720         silc_packet_stream_unref(ctx->sock);
721       router->backup = TRUE;
722       router->backup_proto = ctx;
723       ctx->sock = sock;
724       silc_packet_stream_ref(sock);
725     }
726   }
727
728   /* Call the resuming protocol if the protocol is active. */
729   if (router->backup) {
730     ctx = router->backup_proto;
731     ctx->type = type;
732
733     for (i = 0; i < ctx->sessions_count; i++) {
734       if (session == ctx->sessions[i].session) {
735         ctx->session = session;
736         silc_schedule_task_add_timeout(server->schedule,
737                                        silc_server_protocol_backup,
738                                        ctx, 0, 1);
739         silc_packet_free(packet);
740         return;
741       }
742     }
743
744     /* If RESUMED received the session ID is zero, execute the protocol. */
745     if (type == SILC_SERVER_BACKUP_RESUMED) {
746       silc_schedule_task_add_timeout(server->schedule,
747                                      silc_server_protocol_backup,
748                                      ctx, 0, 1);
749       silc_packet_free(packet);
750       return;
751     }
752
753     SILC_LOG_ERROR(("Unknown backup resuming session %d", session));
754     silc_packet_free(packet);
755     return;
756   }
757
758   silc_packet_free(packet);
759 }
760
761 /* Task that is called after backup router has connected back to
762    primary router and we are starting the resuming protocol */
763
764 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
765 {
766   SilcServerBackupProtocolContext proto_ctx =
767     (SilcServerBackupProtocolContext)context;
768   SilcServer server = proto_ctx->server;
769
770   SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
771   SILC_LOG_INFO(("Starting backup resuming protocol"));
772
773   /* Register protocol timeout */
774   silc_schedule_task_add_timeout(server->schedule,
775                                  silc_server_backup_timeout,
776                                  proto_ctx, 30, 0);
777
778   /* Run the backup resuming protocol */
779   silc_schedule_task_add_timeout(server->schedule,
780                                  silc_server_protocol_backup,
781                                  proto_ctx, 0, 0);
782 }
783
784 SILC_TASK_CALLBACK(silc_server_backup_connected_again)
785 {
786   SilcServer server = app_context;
787   SilcServerConfigRouter *primary;
788
789   if (server->server_shutdown)
790     return;
791
792   primary = silc_server_config_get_primary_router(server);
793   if (primary) {
794     if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
795                                          primary->host, primary->port))
796       silc_server_create_connection(server, FALSE, FALSE,
797                                     primary->host, primary->port,
798                                     silc_server_backup_connected,
799                                     context);
800   }
801 }
802
803 /* Called when we've established connection back to our primary router
804    when we've acting as backup router and have replaced the primary router
805    in the cell. This function will start the backup resuming protocol. */
806
807 void silc_server_backup_connected(SilcServer server,
808                                   SilcServerEntry server_entry,
809                                   void *context)
810 {
811   SilcServerBackupProtocolContext proto_ctx;
812   SilcPacketStream sock;
813
814   if (!server_entry) {
815     /* Try again */
816     silc_schedule_task_add_timeout(server->schedule,
817                                    silc_server_backup_connected_again,
818                                    context, 5, 0);
819     return;
820   }
821
822   sock = server_entry->connection;
823   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
824   proto_ctx->server = server;
825   proto_ctx->sock = sock;
826   proto_ctx->responder = FALSE;
827   proto_ctx->type = SILC_SERVER_BACKUP_START;
828   proto_ctx->start = time(0);
829   silc_packet_stream_ref(sock);
830
831   /* Start through scheduler */
832   silc_schedule_task_add_timeout(server->schedule,
833                                  silc_server_backup_connected_later,
834                                  proto_ctx, 0, 1);
835 }
836
837 SILC_TASK_CALLBACK(silc_server_backup_connect_primary_again)
838 {
839   SilcServer server = app_context;
840   SilcServerConfigRouter *primary;
841
842   primary = silc_server_config_get_primary_router(server);
843   if (primary) {
844     if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
845                                          primary->host, primary->port))
846       silc_server_create_connection(server, FALSE, FALSE,
847                                     primary->host, primary->port,
848                                     silc_server_backup_connect_primary,
849                                     context);
850   }
851 }
852
853 /* Called when normal server has connected to its primary router after
854    backup router has sent the START packet in reusming protocol. We will
855    move the protocol context from the backup router connection to the
856    primary router. */
857
858 static void silc_server_backup_connect_primary(SilcServer server,
859                                                SilcServerEntry server_entry,
860                                                void *context)
861 {
862   SilcPacketStream backup_router = context;
863   SilcIDListData idata = silc_packet_get_context(backup_router);
864   SilcServerEntry router = (SilcServerEntry)idata;
865   SilcServerBackupProtocolContext ctx;
866   SilcPacketStream sock;
867   unsigned char data[2];
868
869   if (!server_entry) {
870     /* Try again */
871     silc_schedule_task_add_timeout(server->schedule,
872                                    silc_server_backup_connect_primary_again,
873                                    context, 0, 0);
874     return;
875   }
876
877   if (!router->backup || !server_entry->connection) {
878     silc_packet_stream_unref(backup_router);
879     return;
880   }
881
882   ctx = router->backup_proto;
883   sock = server_entry->connection;
884   idata = (SilcIDListData)server_entry;
885
886   SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
887   SILC_LOG_INFO(("Sending CONNECTED (session %d) to backup router",
888                 ctx->session));
889
890   /* Send the CONNECTED packet back to the backup router. */
891   data[0] = SILC_SERVER_BACKUP_CONNECTED;
892   data[1] = ctx->session;
893   silc_server_packet_send(server, backup_router,
894                           SILC_PACKET_RESUME_ROUTER, 0, data, 2);
895
896   /* The primary connection is disabled until it sends the RESUMED packet
897      to us. */
898   idata->status |= SILC_IDLIST_STATUS_DISABLED;
899
900   /* Move this protocol context from this backup router connection to
901      the primary router connection since it will send the subsequent
902      packets in this protocol. We don't talk with backup router
903      anymore. */
904   if (ctx->sock)
905     silc_packet_stream_unref(ctx->sock);
906   ctx->sock = sock;
907   silc_packet_stream_ref(sock);
908   server_entry->backup = TRUE;
909   server_entry->backup_proto = ctx;
910   router->backup = FALSE;
911   router->backup_proto = NULL;
912
913   /* Unref */
914   silc_packet_stream_unref(backup_router);
915 }
916
917 /* Timeout callback used by the backup router to send the ENDING packet
918    to primary router to indicate that it can now resume as being primary
919    router. All CONNECTED packets has been received when we reach this. */
920
921 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
922 {
923   SilcServerBackupProtocolContext ctx = context;
924   SilcServer server = ctx->server;
925   unsigned char data[2];
926   int i;
927
928   SILC_LOG_DEBUG(("Start"));
929
930   for (i = 0; i < ctx->sessions_count; i++)
931     if (ctx->sessions[i].server_entry == silc_packet_get_context(ctx->sock))
932       ctx->session = ctx->sessions[i].session;
933
934   /* We've received all the CONNECTED packets and now we'll send the
935      ENDING packet to the new primary router. */
936   data[0] = SILC_SERVER_BACKUP_ENDING;
937   data[1] = ctx->session;
938   silc_server_packet_send(server, ctx->sock, SILC_PACKET_RESUME_ROUTER, 0,
939                           data, sizeof(data));
940
941   /* The protocol will go to END state. */
942   ctx->state = 250;
943 }
944
945 /* Backup resuming protocol. This protocol is executed when the primary
946    router wants to resume its position as being primary router. */
947
948 SILC_TASK_CALLBACK(silc_server_protocol_backup)
949 {
950   SilcServerBackupProtocolContext ctx = context;
951   SilcServer server = ctx->server;
952   SilcServerEntry server_entry = NULL;
953   SilcPacketStream sock = NULL;
954   unsigned char data[2];
955   SilcDList list;
956   int i;
957
958   if (!ctx->state)
959     ctx->state = 1;
960
961   switch(ctx->state) {
962   case 1:
963     if (ctx->responder == FALSE) {
964       /*
965        * Initiator (backup router)
966        */
967
968       /* Send the START packet to primary router and normal servers. The
969          packet will indicate to the primary router that it has been replaced
970          by us.  For normal servers it means that we will be resigning as
971          being primary router shortly. */
972       list = silc_packet_engine_get_streams(server->packet_engine);
973       if (!list)
974         return;
975
976       silc_dlist_start(list);
977       while ((sock = silc_dlist_get(list))) {
978         server_entry = silc_packet_get_context(sock);
979
980         if (!server_entry || server_entry == server->id_entry ||
981             (server_entry->data.conn_type != SILC_CONN_ROUTER &&
982              server_entry->data.conn_type != SILC_CONN_SERVER))
983           continue;
984
985         if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
986           continue;
987
988         ctx->sessions = silc_realloc(ctx->sessions,
989                                      sizeof(*ctx->sessions) *
990                                      (ctx->sessions_count + 1));
991         ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
992         ctx->sessions[ctx->sessions_count].connected = FALSE;
993         ctx->sessions[ctx->sessions_count].server_entry = server_entry;
994
995         SILC_LOG_DEBUG(("Sending START to %s (session %d)",
996                         server_entry->server_name, ctx->sessions_count));
997         SILC_LOG_INFO(("Expecting CONNECTED from %s (session %d)",
998                        server_entry->server_name, ctx->sessions_count));
999
1000         /* This connection is performing this protocol too now */
1001         server_entry->backup = TRUE;
1002         server_entry->backup_proto = ctx;
1003
1004         data[0] = SILC_SERVER_BACKUP_START;
1005         data[1] = ctx->sessions_count;
1006         silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1007                                 data, sizeof(data));
1008         ctx->sessions_count++;
1009       }
1010       silc_packet_engine_free_streams_list(list);
1011
1012       /* Announce data to the new primary to be. */
1013       silc_server_announce_servers(server, TRUE, 0, ctx->sock);
1014       silc_server_announce_clients(server, 0, ctx->sock);
1015       silc_server_announce_channels(server, 0, ctx->sock);
1016
1017       ctx->state++;
1018
1019     } else {
1020       /*
1021        * Responder (all servers and routers)
1022        */
1023       SilcServerConfigRouter *primary;
1024
1025       /* We should have received START packet */
1026       if (ctx->type != SILC_SERVER_BACKUP_START) {
1027         SILC_LOG_ERROR(("Bad resume router packet START %d", ctx->type));
1028         break;
1029       }
1030
1031       /* Connect to the primary router that was down that is now supposed
1032          to be back online. We send the CONNECTED packet after we've
1033          established the connection to the primary router. */
1034       primary = silc_server_config_get_primary_router(server);
1035       if (primary && server->backup_primary &&
1036           !silc_server_num_sockets_by_remote(server,
1037                                              silc_net_is_ip(primary->host) ?
1038                                              primary->host : NULL,
1039                                              silc_net_is_ip(primary->host) ?
1040                                              NULL : primary->host,
1041                                              primary->port,
1042                                              SILC_CONN_ROUTER)) {
1043         SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
1044                         ctx->session));
1045         silc_packet_stream_ref(ctx->sock);
1046         silc_server_create_connection(server, FALSE, FALSE,
1047                                       primary->host, primary->port,
1048                                       silc_server_backup_connect_primary,
1049                                       ctx->sock);
1050       } else {
1051         /* Nowhere to connect just return the CONNECTED packet */
1052         SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
1053                         ctx->session));
1054         SILC_LOG_INFO(("Sending CONNECTED (session %d) to backup router",
1055                       ctx->session));
1056
1057         /* Send the CONNECTED packet back to the backup router. */
1058         data[0] = SILC_SERVER_BACKUP_CONNECTED;
1059         data[1] = ctx->session;
1060         silc_server_packet_send(server, ctx->sock,
1061                                 SILC_PACKET_RESUME_ROUTER, 0,
1062                                 data, sizeof(data));
1063       }
1064
1065       /* Add this resuming session */
1066       ctx->sessions = silc_realloc(ctx->sessions,
1067                                    sizeof(*ctx->sessions) *
1068                                    (ctx->sessions_count + 1));
1069       ctx->sessions[ctx->sessions_count].session = ctx->session;
1070       ctx->sessions_count++;
1071
1072       /* Normal server goes directly to the END state. */
1073       if (server->server_type == SILC_ROUTER &&
1074           (!server->router ||
1075            server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
1076         ctx->state++;
1077       else
1078         ctx->state = 250;
1079     }
1080     break;
1081
1082   case 2:
1083     if (ctx->responder == FALSE) {
1084       /*
1085        * Initiator (backup router)
1086        */
1087
1088       /* We should have received CONNECTED packet */
1089       if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
1090         SILC_LOG_ERROR(("Bad resume router packet CONNECTED %d", ctx->type));
1091         break;
1092       }
1093
1094       for (i = 0; i < ctx->sessions_count; i++) {
1095         if (ctx->sessions[i].session == ctx->session) {
1096           ctx->sessions[i].connected = TRUE;
1097           SILC_LOG_INFO(("Received CONNECTED from %s (session %d)",
1098                          ctx->sessions[i].server_entry->server_name,
1099                          ctx->session));
1100           SILC_LOG_DEBUG(("Received CONNECTED (session %d)", ctx->session));
1101           break;
1102         }
1103       }
1104
1105       /* See if all returned CONNECTED, if not, then continue waiting. */
1106       for (i = 0; i < ctx->sessions_count; i++) {
1107         if (!ctx->sessions[i].connected)
1108           return;
1109       }
1110
1111       SILC_LOG_INFO(("All sessions have returned CONNECTED packets, "
1112                      "continuing"));
1113       SILC_LOG_DEBUG(("Sending ENDING packet to primary router"));
1114
1115       /* The ENDING is sent with timeout, and then we continue to the
1116          END state in the protocol. */
1117       silc_schedule_task_add_timeout(server->schedule,
1118                                      silc_server_backup_send_resumed,
1119                                      ctx, 1, 0);
1120       return;
1121
1122     } else {
1123       /*
1124        * Responder (primary router)
1125        */
1126
1127       /* We should have been received ENDING packet */
1128       if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
1129         SILC_LOG_ERROR(("Bad resume router packet ENDING %d", ctx->type));
1130         break;
1131       }
1132
1133       SILC_LOG_DEBUG(("Received ENDING packet, we are going to resume now"));
1134
1135       /* Switch announced informations to our primary router of using the
1136          backup router. */
1137       silc_server_local_servers_toggle_enabled(server, TRUE);
1138       silc_server_update_servers_by_server(server,
1139                                            silc_packet_get_context(ctx->sock),
1140                                            server->router);
1141       silc_server_update_clients_by_server(server,
1142                                            silc_packet_get_context(ctx->sock),
1143                                            server->router, TRUE);
1144
1145       /* We as primary router now must send RESUMED packets to all servers
1146          and routers so that they know we are back.   For backup router we
1147          send the packet last so that we give the backup as much time as
1148          possible to deal with message routing at this critical moment. */
1149       list = silc_packet_engine_get_streams(server->packet_engine);
1150       if (!list)
1151         return;
1152
1153       silc_dlist_start(list);
1154       while ((sock = silc_dlist_get(list))) {
1155         server_entry = silc_packet_get_context(sock);
1156
1157         if (!server_entry || server_entry == server->id_entry ||
1158             (server_entry->data.conn_type != SILC_CONN_ROUTER &&
1159              server_entry->data.conn_type != SILC_CONN_SERVER))
1160           continue;
1161
1162         /* Send to backup last */
1163         if (sock == ctx->sock)
1164           continue;
1165
1166         server_entry = silc_packet_get_context(sock);
1167         server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1168
1169         SILC_LOG_DEBUG(("Sending RESUMED to %s", server_entry->server_name));
1170         SILC_LOG_INFO(("Sending RESUMED to %s", server_entry->server_name));
1171
1172         /* This connection is performing this protocol too now */
1173         server_entry->backup = TRUE;
1174         server_entry->backup_proto = ctx;
1175
1176         data[0] = SILC_SERVER_BACKUP_RESUMED;
1177         data[1] = 0;
1178         silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1179                                 data, sizeof(data));
1180       }
1181
1182       /* Now send the same packet to backup */
1183       if (sock != ctx->sock) {
1184         sleep(1);
1185         sock = ctx->sock;
1186         server_entry = silc_packet_get_context(sock);
1187         server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1188
1189         SILC_LOG_DEBUG(("Sending RESUMED to %s", server_entry->server_name));
1190         SILC_LOG_INFO(("Sending RESUMED to %s", server_entry->server_name));
1191
1192         /* This connection is performing this protocol too now */
1193         server_entry->backup = TRUE;
1194         server_entry->backup_proto = ctx;
1195
1196         data[0] = SILC_SERVER_BACKUP_RESUMED;
1197         data[1] = 0;
1198         silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1199                                 data, sizeof(data));
1200       }
1201       silc_packet_engine_free_streams_list(list);
1202
1203       /* We are now resumed and are back as primary router in the cell. */
1204       SILC_LOG_INFO(("We are now the primary router of our cell again"));
1205       server->wait_backup = FALSE;
1206
1207       /* Announce WATCH list a little later */
1208       silc_packet_stream_ref(ctx->sock);
1209       silc_schedule_task_add_timeout(server->schedule,
1210                                      silc_server_backup_announce_watches,
1211                                      ctx->sock, 4, 0);
1212
1213       /* For us this is the end of this protocol. */
1214       silc_schedule_task_add_timeout(server->schedule,
1215                                      silc_server_protocol_backup_done,
1216                                      ctx, 0, 1);
1217     }
1218     break;
1219
1220   case 250:
1221     {
1222       /*
1223        * Responder (backup router, servers, and remote router)
1224        */
1225       SilcServerEntry router, backup_router;
1226
1227       /* We should have been received RESUMED from our primary router. */
1228       if (ctx->type != SILC_SERVER_BACKUP_RESUMED) {
1229         SILC_LOG_ERROR(("Bad resume router packet RESUMED %d", ctx->type));
1230         break;
1231       }
1232
1233       SILC_LOG_INFO(("Received RESUMED from new primary router"));
1234
1235       /* If we are the backup router, mark that we are no longer primary
1236          but are back to backup router status. */
1237       if (server->backup_router)
1238         server->server_type = SILC_BACKUP_ROUTER;
1239
1240       /* We have now new primary router. All traffic goes there from now on. */
1241       router = silc_packet_get_context(ctx->sock);
1242       if (silc_server_backup_replaced_get(server, router->id,
1243                                           &backup_router)) {
1244
1245         if (backup_router == server->router) {
1246           /* We have new primary router now */
1247           server->id_entry->router = router;
1248           server->router = router;
1249           SILC_LOG_INFO(("Switching back to primary router %s",
1250                          server->router->server_name));
1251         } else {
1252           /* We are connected to new primary and now continue using it */
1253           SILC_LOG_INFO(("Resuming the use of primary router %s",
1254                          router->server_name));
1255         }
1256         server->backup_primary = FALSE;
1257         sock = router->connection;
1258
1259         /* Update the client entries of the backup router to the new
1260            router */
1261         silc_server_local_servers_toggle_enabled(server, FALSE);
1262         router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1263         silc_server_update_servers_by_server(server, backup_router, router);
1264         silc_server_update_clients_by_server(
1265                                    server, NULL, router,
1266                                    server->server_type == SILC_BACKUP_ROUTER);
1267         if (server->server_type == SILC_SERVER)
1268           silc_server_update_channels_by_server(server, backup_router, router);
1269         silc_server_backup_replaced_del(server, backup_router);
1270       }
1271
1272       /* Send notify about primary router going down to local operators */
1273       SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1274                              SILC_NOTIFY_TYPE_NONE,
1275                              ("%s resumed the use of primary router %s",
1276                               server->server_name,
1277                               server->router->server_name));
1278
1279       /* Protocol has ended, call the final callback */
1280       silc_schedule_task_add_timeout(server->schedule,
1281                                      silc_server_protocol_backup_done,
1282                                      ctx, 0, 1);
1283     }
1284     break;
1285
1286   case 251:
1287     /* Protocol has ended, call the final callback */
1288     silc_schedule_task_add_timeout(server->schedule,
1289                                    silc_server_protocol_backup_done,
1290                                    ctx, 0, 1);
1291     break;
1292
1293   case 252:
1294     /* Protocol has ended, call the final callback */
1295     SILC_LOG_ERROR(("Error during backup resume: received Failure"));
1296     ctx->received_failure = TRUE;
1297     silc_schedule_task_add_timeout(server->schedule,
1298                                    silc_server_protocol_backup_done,
1299                                    ctx, 0, 1);
1300     break;
1301
1302   default:
1303     break;
1304   }
1305 }
1306
1307 /* Final resuming protocol completion callback */
1308
1309 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1310 {
1311   SilcServerBackupProtocolContext ctx = context;
1312   SilcServer server = ctx->server;
1313   SilcDList list;
1314   SilcServerEntry server_entry;
1315   SilcPacketStream sock;
1316   SilcBool error;
1317
1318   silc_schedule_task_del_by_context(server->schedule, ctx);
1319
1320   error = ctx->error;
1321
1322   if (error)
1323     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1324
1325   if (server->server_shutdown)
1326     return;
1327
1328   /* Remove this protocol from all server entries that has it */
1329   list = silc_packet_engine_get_streams(server->packet_engine);
1330   if (!list)
1331     return;
1332
1333   silc_dlist_start(list);
1334   while ((sock = silc_dlist_get(list))) {
1335     server_entry = silc_packet_get_context(sock);
1336     if (!server_entry)
1337       continue;
1338
1339     if (server_entry->data.conn_type != SILC_CONN_ROUTER &&
1340         server_entry->data.conn_type != SILC_CONN_SERVER)
1341       continue;
1342
1343     if (server_entry->backup_proto == ctx) {
1344       if (error) {
1345
1346         if (server->server_type == SILC_SERVER &&
1347             server_entry->server_type == SILC_ROUTER)
1348           continue;
1349
1350         /* Backup router */
1351         if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
1352           if (ctx->sock == sock) {
1353             silc_packet_stream_unref(sock);
1354             ctx->sock = NULL;
1355           }
1356
1357           /* If failed after 10 attempts, it won't work, give up */
1358           if (ctx->initiator_restart > 10)
1359             ctx->received_failure = TRUE;
1360
1361           if (!ctx->received_failure) {
1362             /* Protocol error, probably timeout. Just restart the protocol. */
1363             SilcServerBackupProtocolContext proto_ctx;
1364
1365             /* Restart the protocol. */
1366             proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1367             proto_ctx->server = server;
1368             proto_ctx->sock = sock;
1369             proto_ctx->responder = FALSE;
1370             proto_ctx->type = SILC_SERVER_BACKUP_START;
1371             proto_ctx->start = time(0);
1372             proto_ctx->initiator_restart = ctx->initiator_restart + 1;
1373             silc_packet_stream_ref(sock);
1374
1375             /* Start through scheduler */
1376             silc_schedule_task_add_timeout(server->schedule,
1377                                            silc_server_backup_connected_later,
1378                                            proto_ctx, 5, 0);
1379           } else {
1380             /* If failure was received, switch back to normal backup router.
1381                For some reason primary wouldn't accept that we were supposed
1382                to perfom resuming protocol. */
1383             server->server_type = SILC_BACKUP_ROUTER;
1384             silc_server_local_servers_toggle_enabled(server, FALSE);
1385             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1386             silc_server_update_servers_by_server(server, server->id_entry,
1387                                                  silc_packet_get_context(sock));
1388             silc_server_update_clients_by_server(server, NULL,
1389                                                  silc_packet_get_context(sock),
1390                                                  TRUE);
1391
1392             /* Announce our clients and channels to the router */
1393             silc_server_announce_clients(server, 0, sock);
1394             silc_server_announce_channels(server, 0, sock);
1395
1396             /* Announce WATCH list a little later */
1397             silc_packet_stream_ref(sock);
1398             silc_schedule_task_add_timeout(server->schedule,
1399                                            silc_server_backup_announce_watches,
1400                                            sock, 5, 0);
1401           }
1402
1403           continue;
1404         }
1405       }
1406
1407       server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1408     }
1409   }
1410   silc_packet_engine_free_streams_list(list);
1411
1412   if (!error) {
1413     SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
1414
1415     if (ctx->type == SILC_SERVER_BACKUP_RESUMED && server->router) {
1416       /* Announce all of our information to the router. */
1417       if (server->server_type == SILC_ROUTER)
1418         silc_server_announce_servers(server, FALSE, 0,
1419                                      server->router->connection);
1420
1421       /* Announce our clients and channels to the router */
1422       silc_server_announce_clients(server, 0, server->router->connection);
1423       silc_server_announce_channels(server, 0, server->router->connection);
1424
1425       /* Announce WATCH list a little later */
1426       silc_packet_stream_ref(server->router->connection);
1427       silc_schedule_task_add_timeout(server->schedule,
1428                                      silc_server_backup_announce_watches,
1429                                      server->router->connection, 4, 0);
1430     }
1431   } else {
1432     /* Error */
1433
1434     if (server->server_type == SILC_SERVER) {
1435       /* If we are still using backup router Send confirmation to backup
1436          that using it is still ok and continue sending traffic there.
1437          The backup will reply with error if it's not ok. */
1438       if (server->router && server->backup_primary) {
1439         /* Send START_USE just in case using backup wouldn't be ok. */
1440         silc_server_backup_send_start_use(server, server->router->connection,
1441                                           FALSE);
1442
1443         /* Check couple of times same START_USE just in case. */
1444         silc_packet_stream_ref(server->router->connection);
1445         silc_schedule_task_add_timeout(server->schedule,
1446                                        silc_server_backup_check_status,
1447                                        server->router->connection,
1448                                        5, 1);
1449         silc_packet_stream_ref(server->router->connection);
1450         silc_schedule_task_add_timeout(server->schedule,
1451                                        silc_server_backup_check_status,
1452                                        server->router->connection,
1453                                        20, 1);
1454         silc_packet_stream_ref(server->router->connection);
1455         silc_schedule_task_add_timeout(server->schedule,
1456                                        silc_server_backup_check_status,
1457                                        server->router->connection,
1458                                        60, 1);
1459       }
1460     }
1461   }
1462
1463   if (ctx->sock) {
1464     SilcServerEntry r = silc_packet_get_context(ctx->sock);
1465     if (r) {
1466       r->backup = FALSE;
1467       r->backup_proto = NULL;
1468     }
1469     silc_packet_stream_unref(ctx->sock);
1470   }
1471   silc_free(ctx->sessions);
1472   silc_free(ctx);
1473 }
1474
1475 SILC_TASK_CALLBACK(silc_server_backup_announce_watches)
1476 {
1477   SilcPacketStream sock = context;
1478   SilcServer server = app_context;
1479   if (silc_packet_stream_is_valid(sock))
1480     silc_server_announce_watches(server, sock);
1481   silc_packet_stream_unref(sock);
1482 }