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