e460c95d720022afabf2d277f2459eb8a3dcca2e
[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   primary = silc_server_config_get_primary_router(server);
790   if (primary) {
791     if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
792                                          primary->host, primary->port))
793       silc_server_create_connection(server, FALSE, FALSE,
794                                     primary->host, primary->port,
795                                     silc_server_backup_connected,
796                                     context);
797   }
798 }
799
800 /* Called when we've established connection back to our primary router
801    when we've acting as backup router and have replaced the primary router
802    in the cell. This function will start the backup resuming protocol. */
803
804 void silc_server_backup_connected(SilcServer server,
805                                   SilcServerEntry server_entry,
806                                   void *context)
807 {
808   SilcServerBackupProtocolContext proto_ctx;
809   SilcPacketStream sock;
810
811   if (!server_entry) {
812     /* Try again */
813     silc_schedule_task_add_timeout(server->schedule,
814                                    silc_server_backup_connected_again,
815                                    context, 5, 0);
816     return;
817   }
818
819   sock = server_entry->connection;
820   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
821   proto_ctx->server = server;
822   proto_ctx->sock = sock;
823   proto_ctx->responder = FALSE;
824   proto_ctx->type = SILC_SERVER_BACKUP_START;
825   proto_ctx->start = time(0);
826   silc_packet_stream_ref(sock);
827
828   /* Start through scheduler */
829   silc_schedule_task_add_timeout(server->schedule,
830                                  silc_server_backup_connected_later,
831                                  proto_ctx, 0, 1);
832 }
833
834 SILC_TASK_CALLBACK(silc_server_backup_connect_primary_again)
835 {
836   SilcServer server = app_context;
837   SilcServerConfigRouter *primary;
838
839   primary = silc_server_config_get_primary_router(server);
840   if (primary) {
841     if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
842                                          primary->host, primary->port))
843       silc_server_create_connection(server, FALSE, FALSE,
844                                     primary->host, primary->port,
845                                     silc_server_backup_connect_primary,
846                                     context);
847   }
848 }
849
850 /* Called when normal server has connected to its primary router after
851    backup router has sent the START packet in reusming protocol. We will
852    move the protocol context from the backup router connection to the
853    primary router. */
854
855 static void silc_server_backup_connect_primary(SilcServer server,
856                                                SilcServerEntry server_entry,
857                                                void *context)
858 {
859   SilcPacketStream backup_router = context;
860   SilcIDListData idata = silc_packet_get_context(backup_router);
861   SilcServerEntry router = (SilcServerEntry)idata;
862   SilcServerBackupProtocolContext ctx;
863   SilcPacketStream sock;
864   unsigned char data[2];
865
866   if (!server_entry) {
867     /* Try again */
868     silc_schedule_task_add_timeout(server->schedule,
869                                    silc_server_backup_connect_primary_again,
870                                    context, 0, 0);
871     return;
872   }
873
874   if (!router->backup || !server_entry->connection) {
875     silc_packet_stream_unref(backup_router);
876     return;
877   }
878
879   ctx = router->backup_proto;
880   sock = server_entry->connection;
881   idata = (SilcIDListData)server_entry;
882
883   SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
884   SILC_LOG_INFO(("Sending CONNECTED (session %d) to backup router",
885                 ctx->session));
886
887   /* Send the CONNECTED packet back to the backup router. */
888   data[0] = SILC_SERVER_BACKUP_CONNECTED;
889   data[1] = ctx->session;
890   silc_server_packet_send(server, backup_router,
891                           SILC_PACKET_RESUME_ROUTER, 0, data, 2);
892
893   /* The primary connection is disabled until it sends the RESUMED packet
894      to us. */
895   idata->status |= SILC_IDLIST_STATUS_DISABLED;
896
897   /* Move this protocol context from this backup router connection to
898      the primary router connection since it will send the subsequent
899      packets in this protocol. We don't talk with backup router
900      anymore. */
901   if (ctx->sock)
902     silc_packet_stream_unref(ctx->sock);
903   ctx->sock = sock;
904   silc_packet_stream_ref(sock);
905   server_entry->backup = TRUE;
906   server_entry->backup_proto = ctx;
907   router->backup = FALSE;
908   router->backup_proto = NULL;
909
910   /* Unref */
911   silc_packet_stream_unref(backup_router);
912 }
913
914 /* Timeout callback used by the backup router to send the ENDING packet
915    to primary router to indicate that it can now resume as being primary
916    router. All CONNECTED packets has been received when we reach this. */
917
918 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
919 {
920   SilcServerBackupProtocolContext ctx = context;
921   SilcServer server = ctx->server;
922   unsigned char data[2];
923   int i;
924
925   SILC_LOG_DEBUG(("Start"));
926
927   for (i = 0; i < ctx->sessions_count; i++)
928     if (ctx->sessions[i].server_entry == silc_packet_get_context(ctx->sock))
929       ctx->session = ctx->sessions[i].session;
930
931   /* We've received all the CONNECTED packets and now we'll send the
932      ENDING packet to the new primary router. */
933   data[0] = SILC_SERVER_BACKUP_ENDING;
934   data[1] = ctx->session;
935   silc_server_packet_send(server, ctx->sock, SILC_PACKET_RESUME_ROUTER, 0,
936                           data, sizeof(data));
937
938   /* The protocol will go to END state. */
939   ctx->state = 250;
940 }
941
942 /* Backup resuming protocol. This protocol is executed when the primary
943    router wants to resume its position as being primary router. */
944
945 SILC_TASK_CALLBACK(silc_server_protocol_backup)
946 {
947   SilcServerBackupProtocolContext ctx = context;
948   SilcServer server = ctx->server;
949   SilcServerEntry server_entry = NULL;
950   SilcPacketStream sock = NULL;
951   unsigned char data[2];
952   SilcDList list;
953   int i;
954
955   if (!ctx->state)
956     ctx->state = 1;
957
958   switch(ctx->state) {
959   case 1:
960     if (ctx->responder == FALSE) {
961       /*
962        * Initiator (backup router)
963        */
964
965       /* Send the START packet to primary router and normal servers. The
966          packet will indicate to the primary router that it has been replaced
967          by us.  For normal servers it means that we will be resigning as
968          being primary router shortly. */
969       list = silc_packet_engine_get_streams(server->packet_engine);
970       if (!list)
971         return;
972
973       silc_dlist_start(list);
974       while ((sock = silc_dlist_get(list))) {
975         server_entry = silc_packet_get_context(sock);
976
977         if (!server_entry || server_entry == server->id_entry ||
978             (server_entry->data.conn_type != SILC_CONN_ROUTER &&
979              server_entry->data.conn_type != SILC_CONN_SERVER))
980           continue;
981
982         if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
983           continue;
984
985         ctx->sessions = silc_realloc(ctx->sessions,
986                                      sizeof(*ctx->sessions) *
987                                      (ctx->sessions_count + 1));
988         ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
989         ctx->sessions[ctx->sessions_count].connected = FALSE;
990         ctx->sessions[ctx->sessions_count].server_entry = server_entry;
991
992         SILC_LOG_DEBUG(("Sending START to %s (session %d)",
993                         server_entry->server_name, ctx->sessions_count));
994         SILC_LOG_INFO(("Expecting CONNECTED from %s (session %d)",
995                        server_entry->server_name, ctx->sessions_count));
996
997         /* This connection is performing this protocol too now */
998         server_entry->backup = TRUE;
999         server_entry->backup_proto = ctx;
1000
1001         data[0] = SILC_SERVER_BACKUP_START;
1002         data[1] = ctx->sessions_count;
1003         silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1004                                 data, sizeof(data));
1005         ctx->sessions_count++;
1006       }
1007       silc_packet_engine_free_streams_list(list);
1008
1009       /* Announce data to the new primary to be. */
1010       silc_server_announce_servers(server, TRUE, 0, ctx->sock);
1011       silc_server_announce_clients(server, 0, ctx->sock);
1012       silc_server_announce_channels(server, 0, ctx->sock);
1013
1014       ctx->state++;
1015
1016     } else {
1017       /*
1018        * Responder (all servers and routers)
1019        */
1020       SilcServerConfigRouter *primary;
1021
1022       /* We should have received START packet */
1023       if (ctx->type != SILC_SERVER_BACKUP_START) {
1024         SILC_LOG_ERROR(("Bad resume router packet START %d", ctx->type));
1025         break;
1026       }
1027
1028       /* Connect to the primary router that was down that is now supposed
1029          to be back online. We send the CONNECTED packet after we've
1030          established the connection to the primary router. */
1031       primary = silc_server_config_get_primary_router(server);
1032       if (primary && server->backup_primary &&
1033           !silc_server_num_sockets_by_remote(server,
1034                                              silc_net_is_ip(primary->host) ?
1035                                              primary->host : NULL,
1036                                              silc_net_is_ip(primary->host) ?
1037                                              NULL : primary->host,
1038                                              primary->port,
1039                                              SILC_CONN_ROUTER)) {
1040         SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
1041                         ctx->session));
1042         silc_packet_stream_ref(ctx->sock);
1043         silc_server_create_connection(server, FALSE, FALSE,
1044                                       primary->host, primary->port,
1045                                       silc_server_backup_connect_primary,
1046                                       ctx->sock);
1047       } else {
1048         /* Nowhere to connect just return the CONNECTED packet */
1049         SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
1050                         ctx->session));
1051         SILC_LOG_INFO(("Sending CONNECTED (session %d) to backup router",
1052                       ctx->session));
1053
1054         /* Send the CONNECTED packet back to the backup router. */
1055         data[0] = SILC_SERVER_BACKUP_CONNECTED;
1056         data[1] = ctx->session;
1057         silc_server_packet_send(server, ctx->sock,
1058                                 SILC_PACKET_RESUME_ROUTER, 0,
1059                                 data, sizeof(data));
1060       }
1061
1062       /* Add this resuming session */
1063       ctx->sessions = silc_realloc(ctx->sessions,
1064                                    sizeof(*ctx->sessions) *
1065                                    (ctx->sessions_count + 1));
1066       ctx->sessions[ctx->sessions_count].session = ctx->session;
1067       ctx->sessions_count++;
1068
1069       /* Normal server goes directly to the END state. */
1070       if (server->server_type == SILC_ROUTER &&
1071           (!server->router ||
1072            server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
1073         ctx->state++;
1074       else
1075         ctx->state = 250;
1076     }
1077     break;
1078
1079   case 2:
1080     if (ctx->responder == FALSE) {
1081       /*
1082        * Initiator (backup router)
1083        */
1084
1085       /* We should have received CONNECTED packet */
1086       if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
1087         SILC_LOG_ERROR(("Bad resume router packet CONNECTED %d", ctx->type));
1088         break;
1089       }
1090
1091       for (i = 0; i < ctx->sessions_count; i++) {
1092         if (ctx->sessions[i].session == ctx->session) {
1093           ctx->sessions[i].connected = TRUE;
1094           SILC_LOG_INFO(("Received CONNECTED from %s (session %d)",
1095                          ctx->sessions[i].server_entry->server_name,
1096                          ctx->session));
1097           SILC_LOG_DEBUG(("Received CONNECTED (session %d)", ctx->session));
1098           break;
1099         }
1100       }
1101
1102       /* See if all returned CONNECTED, if not, then continue waiting. */
1103       for (i = 0; i < ctx->sessions_count; i++) {
1104         if (!ctx->sessions[i].connected)
1105           return;
1106       }
1107
1108       SILC_LOG_INFO(("All sessions have returned CONNECTED packets, "
1109                      "continuing"));
1110       SILC_LOG_DEBUG(("Sending ENDING packet to primary router"));
1111
1112       /* The ENDING is sent with timeout, and then we continue to the
1113          END state in the protocol. */
1114       silc_schedule_task_add_timeout(server->schedule,
1115                                      silc_server_backup_send_resumed,
1116                                      ctx, 1, 0);
1117       return;
1118
1119     } else {
1120       /*
1121        * Responder (primary router)
1122        */
1123
1124       /* We should have been received ENDING packet */
1125       if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
1126         SILC_LOG_ERROR(("Bad resume router packet ENDING %d", ctx->type));
1127         break;
1128       }
1129
1130       SILC_LOG_DEBUG(("Received ENDING packet, we are going to resume now"));
1131
1132       /* Switch announced informations to our primary router of using the
1133          backup router. */
1134       silc_server_local_servers_toggle_enabled(server, TRUE);
1135       silc_server_update_servers_by_server(server,
1136                                            silc_packet_get_context(ctx->sock),
1137                                            server->router);
1138       silc_server_update_clients_by_server(server,
1139                                            silc_packet_get_context(ctx->sock),
1140                                            server->router, TRUE);
1141
1142       /* We as primary router now must send RESUMED packets to all servers
1143          and routers so that they know we are back.   For backup router we
1144          send the packet last so that we give the backup as much time as
1145          possible to deal with message routing at this critical moment. */
1146       list = silc_packet_engine_get_streams(server->packet_engine);
1147       if (!list)
1148         return;
1149
1150       silc_dlist_start(list);
1151       while ((sock = silc_dlist_get(list))) {
1152         server_entry = silc_packet_get_context(sock);
1153
1154         if (!server_entry || server_entry == server->id_entry ||
1155             (server_entry->data.conn_type != SILC_CONN_ROUTER &&
1156              server_entry->data.conn_type != SILC_CONN_SERVER))
1157           continue;
1158
1159         /* Send to backup last */
1160         if (sock == ctx->sock)
1161           continue;
1162
1163         server_entry = silc_packet_get_context(sock);
1164         server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1165
1166         SILC_LOG_DEBUG(("Sending RESUMED to %s", server_entry->server_name));
1167         SILC_LOG_INFO(("Sending RESUMED to %s", server_entry->server_name));
1168
1169         /* This connection is performing this protocol too now */
1170         server_entry->backup = TRUE;
1171         server_entry->backup_proto = ctx;
1172
1173         data[0] = SILC_SERVER_BACKUP_RESUMED;
1174         data[1] = 0;
1175         silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1176                                 data, sizeof(data));
1177       }
1178
1179       /* Now send the same packet to backup */
1180       if (sock != ctx->sock) {
1181         sleep(1);
1182         sock = ctx->sock;
1183         server_entry = silc_packet_get_context(sock);
1184         server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1185
1186         SILC_LOG_DEBUG(("Sending RESUMED to %s", server_entry->server_name));
1187         SILC_LOG_INFO(("Sending RESUMED to %s", server_entry->server_name));
1188
1189         /* This connection is performing this protocol too now */
1190         server_entry->backup = TRUE;
1191         server_entry->backup_proto = ctx;
1192
1193         data[0] = SILC_SERVER_BACKUP_RESUMED;
1194         data[1] = 0;
1195         silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
1196                                 data, sizeof(data));
1197       }
1198       silc_packet_engine_free_streams_list(list);
1199
1200       /* We are now resumed and are back as primary router in the cell. */
1201       SILC_LOG_INFO(("We are now the primary router of our cell again"));
1202       server->wait_backup = FALSE;
1203
1204       /* Announce WATCH list a little later */
1205       silc_packet_stream_ref(ctx->sock);
1206       silc_schedule_task_add_timeout(server->schedule,
1207                                      silc_server_backup_announce_watches,
1208                                      ctx->sock, 4, 0);
1209
1210       /* For us this is the end of this protocol. */
1211       silc_schedule_task_add_timeout(server->schedule,
1212                                      silc_server_protocol_backup_done,
1213                                      ctx, 0, 1);
1214     }
1215     break;
1216
1217   case 250:
1218     {
1219       /*
1220        * Responder (backup router, servers, and remote router)
1221        */
1222       SilcServerEntry router, backup_router;
1223
1224       /* We should have been received RESUMED from our primary router. */
1225       if (ctx->type != SILC_SERVER_BACKUP_RESUMED) {
1226         SILC_LOG_ERROR(("Bad resume router packet RESUMED %d", ctx->type));
1227         break;
1228       }
1229
1230       SILC_LOG_INFO(("Received RESUMED from new primary router"));
1231
1232       /* If we are the backup router, mark that we are no longer primary
1233          but are back to backup router status. */
1234       if (server->backup_router)
1235         server->server_type = SILC_BACKUP_ROUTER;
1236
1237       /* We have now new primary router. All traffic goes there from now on. */
1238       router = silc_packet_get_context(ctx->sock);
1239       if (silc_server_backup_replaced_get(server, router->id,
1240                                           &backup_router)) {
1241
1242         if (backup_router == server->router) {
1243           /* We have new primary router now */
1244           server->id_entry->router = router;
1245           server->router = router;
1246           SILC_LOG_INFO(("Switching back to primary router %s",
1247                          server->router->server_name));
1248         } else {
1249           /* We are connected to new primary and now continue using it */
1250           SILC_LOG_INFO(("Resuming the use of primary router %s",
1251                          router->server_name));
1252         }
1253         server->backup_primary = FALSE;
1254         sock = router->connection;
1255
1256         /* Update the client entries of the backup router to the new
1257            router */
1258         silc_server_local_servers_toggle_enabled(server, FALSE);
1259         router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1260         silc_server_update_servers_by_server(server, backup_router, router);
1261         silc_server_update_clients_by_server(
1262                                    server, NULL, router,
1263                                    server->server_type == SILC_BACKUP_ROUTER);
1264         if (server->server_type == SILC_SERVER)
1265           silc_server_update_channels_by_server(server, backup_router, router);
1266         silc_server_backup_replaced_del(server, backup_router);
1267       }
1268
1269       /* Send notify about primary router going down to local operators */
1270       SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1271                              SILC_NOTIFY_TYPE_NONE,
1272                              ("%s resumed the use of primary router %s",
1273                               server->server_name,
1274                               server->router->server_name));
1275
1276       /* Protocol has ended, call the final callback */
1277       silc_schedule_task_add_timeout(server->schedule,
1278                                      silc_server_protocol_backup_done,
1279                                      ctx, 0, 1);
1280     }
1281     break;
1282
1283   case 251:
1284     /* Protocol has ended, call the final callback */
1285     silc_schedule_task_add_timeout(server->schedule,
1286                                    silc_server_protocol_backup_done,
1287                                    ctx, 0, 1);
1288     break;
1289
1290   case 252:
1291     /* Protocol has ended, call the final callback */
1292     SILC_LOG_ERROR(("Error during backup resume: received Failure"));
1293     ctx->received_failure = TRUE;
1294     silc_schedule_task_add_timeout(server->schedule,
1295                                    silc_server_protocol_backup_done,
1296                                    ctx, 0, 1);
1297     break;
1298
1299   default:
1300     break;
1301   }
1302 }
1303
1304 /* Final resuming protocol completion callback */
1305
1306 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1307 {
1308   SilcServerBackupProtocolContext ctx = context;
1309   SilcServer server = ctx->server;
1310   SilcDList list;
1311   SilcServerEntry server_entry;
1312   SilcPacketStream sock;
1313   SilcBool error;
1314
1315   silc_schedule_task_del_by_context(server->schedule, ctx);
1316
1317   error = ctx->error;
1318
1319   if (error)
1320     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1321
1322   if (server->server_shutdown)
1323     return;
1324
1325   /* Remove this protocol from all server entries that has it */
1326   list = silc_packet_engine_get_streams(server->packet_engine);
1327   if (!list)
1328     return;
1329
1330   silc_dlist_start(list);
1331   while ((sock = silc_dlist_get(list))) {
1332     server_entry = silc_packet_get_context(sock);
1333     if (!server_entry)
1334       continue;
1335
1336     if (server_entry->data.conn_type != SILC_CONN_ROUTER &&
1337         server_entry->data.conn_type != SILC_CONN_SERVER)
1338       continue;
1339
1340     if (server_entry->backup_proto == ctx) {
1341       if (error) {
1342
1343         if (server->server_type == SILC_SERVER &&
1344             server_entry->server_type == SILC_ROUTER)
1345           continue;
1346
1347         /* Backup router */
1348         if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
1349           if (ctx->sock == sock) {
1350             silc_packet_stream_unref(sock);
1351             ctx->sock = NULL;
1352           }
1353
1354           /* If failed after 10 attempts, it won't work, give up */
1355           if (ctx->initiator_restart > 10)
1356             ctx->received_failure = TRUE;
1357
1358           if (!ctx->received_failure) {
1359             /* Protocol error, probably timeout. Just restart the protocol. */
1360             SilcServerBackupProtocolContext proto_ctx;
1361
1362             /* Restart the protocol. */
1363             proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1364             proto_ctx->server = server;
1365             proto_ctx->sock = sock;
1366             proto_ctx->responder = FALSE;
1367             proto_ctx->type = SILC_SERVER_BACKUP_START;
1368             proto_ctx->start = time(0);
1369             proto_ctx->initiator_restart = ctx->initiator_restart + 1;
1370             silc_packet_stream_ref(sock);
1371
1372             /* Start through scheduler */
1373             silc_schedule_task_add_timeout(server->schedule,
1374                                            silc_server_backup_connected_later,
1375                                            proto_ctx, 5, 0);
1376           } else {
1377             /* If failure was received, switch back to normal backup router.
1378                For some reason primary wouldn't accept that we were supposed
1379                to perfom resuming protocol. */
1380             server->server_type = SILC_BACKUP_ROUTER;
1381             silc_server_local_servers_toggle_enabled(server, FALSE);
1382             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1383             silc_server_update_servers_by_server(server, server->id_entry,
1384                                                  silc_packet_get_context(sock));
1385             silc_server_update_clients_by_server(server, NULL,
1386                                                  silc_packet_get_context(sock),
1387                                                  TRUE);
1388
1389             /* Announce our clients and channels to the router */
1390             silc_server_announce_clients(server, 0, sock);
1391             silc_server_announce_channels(server, 0, sock);
1392
1393             /* Announce WATCH list a little later */
1394             silc_packet_stream_ref(sock);
1395             silc_schedule_task_add_timeout(server->schedule,
1396                                            silc_server_backup_announce_watches,
1397                                            sock, 5, 0);
1398           }
1399
1400           continue;
1401         }
1402       }
1403
1404       server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1405     }
1406   }
1407   silc_packet_engine_free_streams_list(list);
1408
1409   if (!error) {
1410     SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
1411
1412     if (ctx->type == SILC_SERVER_BACKUP_RESUMED && server->router) {
1413       /* Announce all of our information to the router. */
1414       if (server->server_type == SILC_ROUTER)
1415         silc_server_announce_servers(server, FALSE, 0,
1416                                      server->router->connection);
1417
1418       /* Announce our clients and channels to the router */
1419       silc_server_announce_clients(server, 0, server->router->connection);
1420       silc_server_announce_channels(server, 0, server->router->connection);
1421
1422       /* Announce WATCH list a little later */
1423       silc_packet_stream_ref(server->router->connection);
1424       silc_schedule_task_add_timeout(server->schedule,
1425                                      silc_server_backup_announce_watches,
1426                                      server->router->connection, 4, 0);
1427     }
1428   } else {
1429     /* Error */
1430
1431     if (server->server_type == SILC_SERVER) {
1432       /* If we are still using backup router Send confirmation to backup
1433          that using it is still ok and continue sending traffic there.
1434          The backup will reply with error if it's not ok. */
1435       if (server->router && server->backup_primary) {
1436         /* Send START_USE just in case using backup wouldn't be ok. */
1437         silc_server_backup_send_start_use(server, server->router->connection,
1438                                           FALSE);
1439
1440         /* Check couple of times same START_USE just in case. */
1441         silc_packet_stream_ref(server->router->connection);
1442         silc_schedule_task_add_timeout(server->schedule,
1443                                        silc_server_backup_check_status,
1444                                        server->router->connection,
1445                                        5, 1);
1446         silc_packet_stream_ref(server->router->connection);
1447         silc_schedule_task_add_timeout(server->schedule,
1448                                        silc_server_backup_check_status,
1449                                        server->router->connection,
1450                                        20, 1);
1451         silc_packet_stream_ref(server->router->connection);
1452         silc_schedule_task_add_timeout(server->schedule,
1453                                        silc_server_backup_check_status,
1454                                        server->router->connection,
1455                                        60, 1);
1456       }
1457     }
1458   }
1459
1460   if (ctx->sock) {
1461     SilcServerEntry r = silc_packet_get_context(ctx->sock);
1462     if (r) {
1463       r->backup = FALSE;
1464       r->backup_proto = NULL;
1465     }
1466     silc_packet_stream_unref(ctx->sock);
1467   }
1468   silc_free(ctx->sessions);
1469   silc_free(ctx);
1470 }
1471
1472 SILC_TASK_CALLBACK(silc_server_backup_announce_watches)
1473 {
1474   SilcPacketStream sock = context;
1475   SilcServer server = app_context;
1476   if (silc_packet_stream_is_valid(sock))
1477     silc_server_announce_watches(server, sock);
1478   silc_packet_stream_unref(sock);
1479 }