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