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