More error printing to backup resuming code.
[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 - 2002 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 static void silc_server_backup_connect_primary(SilcServer server,
26                                                SilcServerEntry server_entry,
27                                                void *context);
28
29 /* Backup router */
30 typedef struct {
31   SilcServerEntry server;
32   SilcIDIP ip;
33   SilcUInt16 port;
34   bool local;
35 } SilcServerBackupEntry;
36
37 /* Holds IP address and port of the primary router that was replaced
38    by backup router. */
39 typedef struct {
40   SilcIDIP ip;
41   SilcUInt16 port;
42   SilcServerEntry server;       /* Backup router that replaced the primary */
43 } SilcServerBackupReplaced;
44
45 /* Backup context */
46 struct SilcServerBackupStruct {
47   SilcServerBackupEntry *servers;
48   SilcUInt32 servers_count;
49   SilcServerBackupReplaced **replaced;
50   SilcUInt32 replaced_count;
51 };
52
53 typedef struct {
54   SilcUInt8 session;
55   bool connected;
56   SilcServerEntry server_entry;
57 } SilcServerBackupProtocolSession;
58
59 /* Backup resuming protocol context  */
60 typedef struct {
61   SilcServer server;
62   SilcSocketConnection sock;
63   bool responder;
64   SilcUInt8 type;
65   SilcUInt8 session;
66   SilcServerBackupProtocolSession *sessions;
67   SilcUInt32 sessions_count;
68   long start;
69 } *SilcServerBackupProtocolContext;
70
71 /* Adds the `backup_server' to be one of our backup router. This can be
72    called multiple times to set multiple backup routers. The `ip' and `port'
73    is the IP and port that the `backup_router' will replace if the `ip'
74    will become unresponsive. If `local' is TRUE then the `backup_server' is
75    in the local cell, if FALSE it is in some other cell. */
76
77 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
78                             const char *ip, int port, bool local)
79 {
80   int i;
81
82   if (!ip)
83     return;
84
85   if (!server->backup) {
86     server->backup = silc_calloc(1, sizeof(*server->backup));
87     if (!server->backup)
88       return;
89   }
90
91   SILC_LOG_DEBUG(("Backup router %s will replace %s",
92                   ((SilcSocketConnection)backup_server->connection)->ip,
93                   ip, port));
94
95   for (i = 0; i < server->backup->servers_count; i++) {
96     if (!server->backup->servers[i].server) {
97       server->backup->servers[i].server = backup_server;
98       server->backup->servers[i].local = local;
99       memset(server->backup->servers[i].ip.data, 0,
100              sizeof(server->backup->servers[i].ip.data));
101       silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
102                         sizeof(server->backup->servers[i].ip.data));
103       return;
104     }
105   }
106
107   i = server->backup->servers_count;
108   server->backup->servers = silc_realloc(server->backup->servers,
109                                          sizeof(*server->backup->servers) *
110                                          (i + 1));
111   server->backup->servers[i].server = backup_server;
112   server->backup->servers[i].local = local;
113   memset(server->backup->servers[i].ip.data, 0,
114          sizeof(server->backup->servers[i].ip.data));
115   silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
116                     sizeof(server->backup->servers[i].ip.data));
117   server->backup->servers_count++;
118 }
119
120 /* Returns backup router for IP and port in `replacing' or NULL if there
121    does not exist backup router. */
122
123 SilcServerEntry silc_server_backup_get(SilcServer server, 
124                                        SilcServerID *server_id)
125 {
126   int i;
127
128   if (!server->backup)
129     return NULL;
130
131   for (i = 0; i < server->backup->servers_count; i++) {
132     if (server->backup->servers[i].server &&
133         !memcmp(&server->backup->servers[i].ip, &server_id->ip.data,
134                 sizeof(server_id->ip.data))) {
135       SILC_LOG_DEBUG(("Found backup router %s for %s",
136                       server->backup->servers[i].server->server_name,
137                       silc_id_render(server_id, SILC_ID_SERVER)));
138       return server->backup->servers[i].server;
139     }
140   }
141
142   return NULL;
143 }
144
145 /* Deletes the backup server `server_entry'. */
146
147 void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry)
148 {
149   int i;
150
151   if (!server->backup)
152     return;
153
154   for (i = 0; i < server->backup->servers_count; i++) {
155     if (server->backup->servers[i].server == server_entry) {
156       SILC_LOG_DEBUG(("Removing %s as backup router",
157                       silc_id_render(server->backup->servers[i].server->id,
158                                      SILC_ID_SERVER)));
159       server->backup->servers[i].server = NULL;
160       memset(server->backup->servers[i].ip.data, 0,
161              sizeof(server->backup->servers[i].ip.data));
162     }
163   }
164 }
165
166 /* Frees all data allocated for backup routers.  Call this after deleting
167    all backup routers and when new routers are added no more, for example
168    when shutting down the server. */
169
170 void silc_server_backup_free(SilcServer server)
171 {
172   int i;
173
174   if (!server->backup)
175     return;
176
177   /* Delete existing servers if caller didn't do it */
178   for (i = 0; i < server->backup->servers_count; i++) {
179     if (server->backup->servers[i].server)
180       silc_server_backup_del(server, server->backup->servers[i].server);
181   }
182
183   silc_free(server->backup->servers);
184   silc_free(server->backup);
185   server->backup = NULL;
186 }
187
188 /* Marks the IP address and port from the `server_id' as  being replaced
189    by backup router indicated by the `server'. If the router connects at
190    a later time we can check whether it has been replaced by an backup
191    router. */
192
193 void silc_server_backup_replaced_add(SilcServer server, 
194                                      SilcServerID *server_id,
195                                      SilcServerEntry server_entry)
196 {
197   int i;
198   SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
199
200   if (!server->backup)
201     server->backup = silc_calloc(1, sizeof(*server->backup));
202   if (!server->backup->replaced) {
203     server->backup->replaced = 
204       silc_calloc(1, sizeof(*server->backup->replaced));
205     server->backup->replaced_count = 1;
206   }
207
208   SILC_LOG_DEBUG(("Replacing router %s with %s",
209                   silc_id_render(server_id, SILC_ID_SERVER),
210                   server_entry->server_name));
211
212   memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
213   r->server = server_entry;
214
215   for (i = 0; i < server->backup->replaced_count; i++) {
216     if (!server->backup->replaced[i]) {
217       server->backup->replaced[i] = r;
218       return;
219     }
220   }
221
222   i = server->backup->replaced_count;
223   server->backup->replaced = silc_realloc(server->backup->replaced,
224                                           sizeof(*server->backup->replaced) *
225                                           (i + 1));
226   server->backup->replaced[i] = r;
227   server->backup->replaced_count++;
228 }
229
230 /* Checks whether the IP address and port from the `server_id' has been
231    replaced by an backup router. If it has been then this returns TRUE
232    and the bacup router entry to the `server' pointer if non-NULL. Returns
233    FALSE if the router is not replaced by backup router. */
234
235 bool silc_server_backup_replaced_get(SilcServer server,
236                                      SilcServerID *server_id,
237                                      SilcServerEntry *server_entry)
238 {
239   int i;
240
241   if (!server->backup || !server->backup->replaced)
242     return FALSE;
243
244   for (i = 0; i < server->backup->replaced_count; i++) {
245     if (!server->backup->replaced[i])
246       continue;
247     if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip.data,
248                 sizeof(server_id->ip.data))) {
249       if (server_entry)
250         *server_entry = server->backup->replaced[i]->server;
251       SILC_LOG_DEBUG(("Router %s is replaced by %s",
252                       silc_id_render(server_id, SILC_ID_SERVER),
253                       server->backup->replaced[i]->server->server_name));
254       return TRUE;
255     }
256   }
257
258   SILC_LOG_DEBUG(("Router %s is not replaced by backup router",
259                   silc_id_render(server_id, SILC_ID_SERVER)));
260   return FALSE;
261 }
262
263 /* Deletes a replaced host by the set `server_entry. */
264
265 void silc_server_backup_replaced_del(SilcServer server,
266                                      SilcServerEntry server_entry)
267 {
268   int i;
269
270   if (!server->backup || !server->backup->replaced)
271     return;
272
273   for (i = 0; i < server->backup->replaced_count; i++) {
274     if (!server->backup->replaced[i])
275       continue;
276     if (server->backup->replaced[i]->server == server_entry) {
277       silc_free(server->backup->replaced[i]);
278       server->backup->replaced[i] = NULL;
279       return;
280     }
281   }
282 }
283
284 /* Broadcast the received packet indicated by `packet' to all of our backup 
285    routers. All router wide information is passed using broadcast packets. 
286    That is why all backup routers need to get this data too. It is expected
287    that the caller already knows that the `packet' is broadcast packet. */
288
289 void silc_server_backup_broadcast(SilcServer server, 
290                                   SilcSocketConnection sender,
291                                   SilcPacketContext *packet)
292 {
293   SilcServerEntry backup;
294   SilcSocketConnection sock;
295   SilcBuffer buffer;
296   const SilcBufferStruct p;
297   SilcIDListData idata;
298   int i;
299
300   if (!server->backup || server->server_type != SILC_ROUTER)
301     return;
302
303   SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
304
305   buffer = packet->buffer;
306   silc_buffer_push(buffer, buffer->data - buffer->head);
307
308   for (i = 0; i < server->backup->servers_count; i++) {
309     backup = server->backup->servers[i].server;
310
311     if (!backup || backup->connection == sender || 
312         server->backup->servers[i].local == FALSE)
313       continue;
314     if (server->backup->servers[i].server == server->id_entry)
315       continue;
316
317     idata = (SilcIDListData)backup;
318     sock = backup->connection;
319
320     if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
321                                   (const SilcBuffer)&p)) {
322       SILC_LOG_ERROR(("Cannot send packet"));
323       return;
324     }
325     silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
326     silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, 
327                         (SilcBuffer)&p, p.len);
328
329     SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len);
330
331     /* Now actually send the packet */
332     silc_server_packet_send_real(server, sock, FALSE);
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                              bool force_send,
353                              bool local)
354 {
355   SilcServerEntry backup;
356   SilcSocketConnection 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_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
374                     silc_get_packet_name(type), sock->hostname, sock->ip));
375
376     silc_server_packet_send(server, backup->connection, type, flags, 
377                             data, data_len, force_send);
378   }
379 }
380
381 /* Same as silc_server_backup_send but sets a specific Destination ID to
382    the packet. The Destination ID is indicated by the `dst_id' and the
383    ID type `dst_id_type'. For example, packets destined to channels must
384    be sent using this function. */
385
386 void silc_server_backup_send_dest(SilcServer server,
387                                   SilcServerEntry sender,
388                                   SilcPacketType type,
389                                   SilcPacketFlags flags,
390                                   void *dst_id,
391                                   SilcIdType dst_id_type,
392                                   unsigned char *data,
393                                   SilcUInt32 data_len,
394                                   bool force_send,
395                                   bool local)
396 {
397   SilcServerEntry backup;
398   SilcSocketConnection sock;
399   int i;
400
401   if (!server->backup || server->server_type != SILC_ROUTER)
402     return;
403
404   for (i = 0; i < server->backup->servers_count; i++) {
405     backup = server->backup->servers[i].server;
406     if (!backup || sender == backup)
407       continue;
408     if (local && server->backup->servers[i].local == FALSE)
409       continue;
410     if (server->backup->servers[i].server == server->id_entry)
411       continue;
412
413     sock = backup->connection;
414
415     SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
416                     silc_get_packet_name(type), sock->hostname, sock->ip));
417
418     silc_server_packet_send_dest(server, backup->connection, type, flags, 
419                                  dst_id, dst_id_type, data, data_len, 
420                                  force_send);
421   }
422 }
423
424 /* Processes incoming RESUME_ROUTER packet. This can give the packet
425    for processing to the protocol handler or allocate new protocol if
426    start command is received. */
427
428 void silc_server_backup_resume_router(SilcServer server, 
429                                       SilcSocketConnection sock, 
430                                       SilcPacketContext *packet)
431 {
432   SilcUInt8 type, session;
433   SilcServerBackupProtocolContext ctx;
434   int i, ret;
435
436   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
437       sock->type == SILC_SOCKET_TYPE_UNKNOWN) {
438     SILC_LOG_DEBUG(("Bad packet received"));
439     return;
440   }
441
442   ret = silc_buffer_unformat(packet->buffer,
443                              SILC_STR_UI_CHAR(&type),
444                              SILC_STR_UI_CHAR(&session),
445                              SILC_STR_END);
446   if (ret < 0) {
447     SILC_LOG_ERROR(("Malformed resume router packet received"));
448     return;
449   }
450   
451   /* Activate the protocol for this socket if necessary */
452   if ((type == SILC_SERVER_BACKUP_RESUMED || 
453       type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
454       sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol && 
455       ((SilcIDListData)sock->user_data)->status & 
456       SILC_IDLIST_STATUS_DISABLED) {
457     SilcServerEntry backup_router;
458
459     if (silc_server_backup_replaced_get(server, 
460                                         ((SilcServerEntry)sock->
461                                          user_data)->id, 
462                                         &backup_router)) {
463       SilcSocketConnection bsock = 
464         (SilcSocketConnection)backup_router->connection;
465       if (bsock->protocol && bsock->protocol->protocol &&
466           bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
467         sock->protocol = bsock->protocol;
468         ctx = sock->protocol->context;
469         ctx->sock = sock;
470       }
471     }
472   }
473
474   /* If the backup resuming protocol is active then process the packet
475      in the protocol. */
476   if (sock->protocol && sock->protocol->protocol &&
477       sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
478     ctx = sock->protocol->context;
479     ctx->type = type;
480
481     if (type != SILC_SERVER_BACKUP_RESUMED &&
482         type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
483       for (i = 0; i < ctx->sessions_count; i++) {
484         if (session == ctx->sessions[i].session) {
485           ctx->session = session;
486           silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
487           return;
488         }
489       }
490     } else {
491       silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
492       return;
493     }
494
495     SILC_LOG_ERROR(("Bad resume router packet RESUMED %d", type));
496     return;
497   }
498
499   /* We don't have protocol active. If we are router and the packet is 
500      coming from our primary router then lets check whether it means we've
501      been replaced by an backup router in my cell. This is usually received
502      immediately after we've connected to our primary router. */
503
504   if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
505       sock && SILC_PRIMARY_ROUTE(server) == sock &&
506       type == SILC_SERVER_BACKUP_REPLACED) {
507     /* We have been replaced by an backup router in our cell. We must
508        mark our primary router connection disabled since we are not allowed
509        to use it at this moment. */
510     SilcIDListData idata = (SilcIDListData)sock->user_data;
511     SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
512                    "wait until backup resuming protocol is executed"));
513     idata->status |= SILC_IDLIST_STATUS_DISABLED;
514     return;
515   }
516
517   if (type == SILC_SERVER_BACKUP_START ||
518       type == SILC_SERVER_BACKUP_START_GLOBAL) {
519     /* We have received a start for resuming protocol. */
520     SilcServerBackupProtocolContext proto_ctx;
521
522     proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
523     proto_ctx->server = server;
524     proto_ctx->sock = sock;
525     proto_ctx->responder = TRUE;
526     proto_ctx->type = type;
527     proto_ctx->session = session;
528     proto_ctx->start = time(0);
529
530     SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
531     SILC_LOG_INFO(("Starting backup resuming protocol"));
532
533     /* Run the backup resuming protocol */
534     silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
535                         &sock->protocol, proto_ctx, 
536                         silc_server_protocol_backup_done);
537     silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
538   }
539 }
540
541 /* Timeout task callback to connect to remote router */
542
543 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
544 {
545   SilcServer server = app_context;
546   SilcServerConnection sconn = (SilcServerConnection)context;
547   int sock;
548   const char *server_ip;
549
550   SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
551                   sconn->remote_port));
552
553   /* Connect to remote host */
554   server_ip = server->config->server_info->primary == NULL ? NULL :
555     server->config->server_info->primary->server_ip;
556   sock = silc_net_create_connection(server_ip, sconn->remote_port,
557                                     sconn->remote_host);
558   if (sock < 0) {
559     silc_schedule_task_add(server->schedule, 0,
560                            silc_server_backup_connect_to_router,
561                            context, 5, 0, SILC_TASK_TIMEOUT, 
562                            SILC_TASK_PRI_NORMAL);
563     return;
564   }
565
566   /* Continue with key exchange protocol */
567   silc_server_start_key_exchange(server, sconn, sock);
568 }
569
570 /* Constantly tries to reconnect to a primary router indicated by the
571    `ip' and `port'. The `connected' callback will be called when the
572    connection is created. */
573
574 void silc_server_backup_reconnect(SilcServer server,
575                                   const char *ip, SilcUInt16 port,
576                                   SilcServerConnectRouterCallback callback,
577                                   void *context)
578 {
579   SilcServerConnection sconn;
580
581   SILC_LOG_INFO(("Attempting to reconnect to primary router"));
582
583   sconn = silc_calloc(1, sizeof(*sconn));
584   sconn->remote_host = strdup(ip);
585   sconn->remote_port = port;
586   sconn->callback = callback;
587   sconn->callback_context = context;
588   sconn->no_reconnect = TRUE;
589   silc_schedule_task_add(server->schedule, 0, 
590                          silc_server_backup_connect_to_router,
591                          sconn, 1, 0, SILC_TASK_TIMEOUT,
592                          SILC_TASK_PRI_NORMAL);
593 }
594
595 /* Task that is called after backup router has connected back to
596    primary router and we are starting the resuming protocol */
597
598 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
599 {
600   SilcServerBackupProtocolContext proto_ctx = 
601     (SilcServerBackupProtocolContext)context;
602   SilcServer server = proto_ctx->server;
603   SilcSocketConnection sock = proto_ctx->sock;
604
605   SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
606   SILC_LOG_INFO(("Starting backup resuming protocol"));
607
608   /* Run the backup resuming protocol */
609   silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
610                       &sock->protocol, proto_ctx, 
611                       silc_server_protocol_backup_done);
612   silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
613 }
614
615 /* Called when we've established connection back to our primary router
616    when we've acting as backup router and have replaced the primary router
617    in the cell. This function will start the backup resuming protocol. */
618
619 void silc_server_backup_connected(SilcServer server,
620                                   SilcServerEntry server_entry,
621                                   void *context)
622 {
623   SilcServerBackupProtocolContext proto_ctx;
624   SilcSocketConnection sock;
625
626   if (!server_entry) {
627     /* Try again */
628     SilcServerConfigRouter *primary;
629     primary = silc_server_config_get_primary_router(server);
630     if (primary)
631       silc_server_backup_reconnect(server,
632                                    primary->host, primary->port,
633                                    silc_server_backup_connected,
634                                    context);
635     return;
636   }
637
638   sock = (SilcSocketConnection)server_entry->connection;
639   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
640   proto_ctx->server = server;
641   proto_ctx->sock = sock;
642   proto_ctx->responder = FALSE;
643   proto_ctx->type = SILC_SERVER_BACKUP_START;
644   proto_ctx->start = time(0);
645
646   /* Start through scheduler */
647   silc_schedule_task_add(server->schedule, 0,
648                          silc_server_backup_connected_later,
649                          proto_ctx, 0, 1,
650                          SILC_TASK_TIMEOUT,
651                          SILC_TASK_PRI_NORMAL);
652 }
653
654 /* Called when normal server has connected to its primary router after
655    backup router has sent the START packet in reusming protocol. We will
656    move the protocol context from the backup router connection to the
657    primary router. */
658
659 static void silc_server_backup_connect_primary(SilcServer server,
660                                                SilcServerEntry server_entry,
661                                                void *context)
662 {
663   SilcSocketConnection backup_router = (SilcSocketConnection)context;
664   SilcServerBackupProtocolContext ctx;
665   SilcSocketConnection sock;
666   SilcIDListData idata;
667   SilcBuffer buffer;
668
669   if (!server_entry) {
670     /* Try again */
671     SilcServerConfigRouter *primary;
672     primary = silc_server_config_get_primary_router(server);
673     if (primary)
674       silc_server_backup_reconnect(server,
675                                    primary->host, primary->port,
676                                    silc_server_backup_connect_primary,
677                                    context);
678     return;
679   }
680
681   ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context;
682   sock = (SilcSocketConnection)server_entry->connection;
683   idata = (SilcIDListData)server_entry;
684
685   SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
686
687   /* Send the CONNECTED packet back to the backup router. */
688   buffer = silc_buffer_alloc(2);
689   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
690   silc_buffer_format(buffer,
691                      SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
692                      SILC_STR_UI_CHAR(ctx->session),
693                      SILC_STR_END);
694   silc_server_packet_send(server, backup_router, 
695                           SILC_PACKET_RESUME_ROUTER, 0, 
696                           buffer->data, buffer->len, FALSE);
697   silc_buffer_free(buffer);
698
699   /* The primary connection is disabled until it sends the RESUMED packet
700      to us. */
701   idata->status |= SILC_IDLIST_STATUS_DISABLED;
702
703   /* Move this protocol context from this backup router connection to
704      the primary router connection since it will send the subsequent
705      packets in this protocol. We don't talk with backup router 
706      anymore. */
707   sock->protocol = backup_router->protocol;
708   ctx->sock = (SilcSocketConnection)server_entry->connection;
709   backup_router->protocol = NULL;
710 }
711
712 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
713 {
714   SilcProtocol protocol = (SilcProtocol)context;
715   SilcServerBackupProtocolContext ctx = protocol->context;
716   SilcServer server = ctx->server;
717   SilcBuffer packet;
718   int i;
719
720   for (i = 0; i < ctx->sessions_count; i++)
721     if (ctx->sessions[i].server_entry == ctx->sock->user_data)
722       ctx->session = ctx->sessions[i].session;
723   
724   /* We've received all the CONNECTED packets and now we'll send the
725      ENDING packet to the new primary router. */
726   packet = silc_buffer_alloc(2);
727   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
728   silc_buffer_format(packet,
729                      SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
730                      SILC_STR_UI_CHAR(ctx->session),
731                      SILC_STR_END);
732   silc_server_packet_send(server, ctx->sock, 
733                           SILC_PACKET_RESUME_ROUTER, 0, 
734                           packet->data, packet->len, FALSE);
735   silc_buffer_free(packet);
736   
737   protocol->state = SILC_PROTOCOL_STATE_END;
738 }
739
740 /* Backup resuming protocol. This protocol is executed when the primary
741    router wants to resume its position as being primary router. */
742
743 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
744 {
745   SilcProtocol protocol = (SilcProtocol)context;
746   SilcServerBackupProtocolContext ctx = protocol->context;
747   SilcServer server = ctx->server;
748   SilcBuffer packet;
749   SilcIDCacheList list;
750   SilcIDCacheEntry id_cache;
751   SilcServerEntry server_entry;
752   int i;
753
754   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
755     protocol->state = SILC_PROTOCOL_STATE_START;
756
757   switch(protocol->state) {
758   case SILC_PROTOCOL_STATE_START:
759     if (ctx->responder == FALSE) {
760       /* Initiator of the protocol. We are backup router */
761
762       packet = silc_buffer_alloc(2);
763       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
764
765       /* Send the START packet to primary router and normal servers. */
766       if (silc_idcache_get_all(server->local_list->servers, &list)) {
767         if (silc_idcache_list_first(list, &id_cache)) {
768           while (id_cache) {
769             server_entry = (SilcServerEntry)id_cache->context;
770             if (!server_entry || (server_entry == server->id_entry) || 
771                 !server_entry->connection || !server_entry->data.send_key ||
772                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
773               if (!silc_idcache_list_next(list, &id_cache))
774                 break;
775               else
776                 continue;
777             }
778
779             ctx->sessions = silc_realloc(ctx->sessions,
780                                          sizeof(*ctx->sessions) *
781                                          (ctx->sessions_count + 1));
782             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
783             ctx->sessions[ctx->sessions_count].connected = FALSE;
784             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
785
786             SILC_LOG_DEBUG(("Sending START to %s (session %d)", 
787                             server_entry->server_name, ctx->sessions_count));
788
789             /* This connection is performing this protocol too now */
790             ((SilcSocketConnection)server_entry->connection)->protocol =
791               protocol;
792
793             if (server_entry->server_type == SILC_ROUTER)
794               packet->data[0] = SILC_SERVER_BACKUP_START;
795             else
796               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
797             packet->data[1] = ctx->sessions_count;
798             silc_server_packet_send(server, server_entry->connection,
799                                     SILC_PACKET_RESUME_ROUTER, 0, 
800                                     packet->data, packet->len, FALSE);
801             ctx->sessions_count++;
802
803             if (!silc_idcache_list_next(list, &id_cache))
804               break;
805           }
806         }
807
808         silc_idcache_list_free(list);
809       }
810
811       if (silc_idcache_get_all(server->global_list->servers, &list)) {
812         if (silc_idcache_list_first(list, &id_cache)) {
813           while (id_cache) {
814             server_entry = (SilcServerEntry)id_cache->context;
815             if (!server_entry || (server_entry == server->id_entry) || 
816                 !server_entry->connection || !server_entry->data.send_key ||
817                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
818               if (!silc_idcache_list_next(list, &id_cache))
819                 break;
820               else
821                 continue;
822             }
823
824             ctx->sessions = silc_realloc(ctx->sessions,
825                                          sizeof(*ctx->sessions) *
826                                          (ctx->sessions_count + 1));
827             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
828             ctx->sessions[ctx->sessions_count].connected = FALSE;
829             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
830
831             SILC_LOG_DEBUG(("Sending START to %s (session %d)", 
832                             server_entry->server_name, ctx->sessions_count));
833
834             /* This connection is performing this protocol too now */
835             ((SilcSocketConnection)server_entry->connection)->protocol =
836               protocol;
837
838             if (server_entry->server_type == SILC_ROUTER)
839               packet->data[0] = SILC_SERVER_BACKUP_START;
840             else
841               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
842             packet->data[1] = ctx->sessions_count;
843             silc_server_packet_send(server, server_entry->connection,
844                                     SILC_PACKET_RESUME_ROUTER, 0, 
845                                     packet->data, packet->len, FALSE);
846             ctx->sessions_count++;
847
848             if (!silc_idcache_list_next(list, &id_cache))
849               break;
850           }
851         }
852
853         silc_idcache_list_free(list);
854       }
855
856       silc_buffer_free(packet);
857
858       /* If we are not standalone and our primary is not the one we've
859          talking to now, then announce our information to it since we
860          haven't done that yet.  Standalone backup router announces
861          these during connecting to the primary. */
862       if (!server->standalone && SILC_PRIMARY_ROUTE(server) != ctx->sock) {
863         silc_server_announce_servers(server, TRUE, 0, ctx->sock);
864         silc_server_announce_clients(server, 0, ctx->sock);
865         silc_server_announce_channels(server, 0, ctx->sock);
866       }
867
868       protocol->state++;
869     } else {
870       /* Responder of the protocol. */
871       SilcServerConfigRouter *primary;
872
873       /* We should have received START or START_GLOBAL packet */
874       if (ctx->type != SILC_SERVER_BACKUP_START &&
875           ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
876         SILC_LOG_ERROR(("Bad resume router packet START %d", ctx->type));
877         break;
878       }
879
880       /* Connect to the primary router that was down that is now supposed
881          to be back online. We send the CONNECTED packet after we've
882          established the connection to the primary router. */
883       primary = silc_server_config_get_primary_router(server);
884       if (primary && server->backup_primary) {
885         SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
886                         ctx->session));
887         silc_server_backup_reconnect(server,
888                                      primary->host, primary->port,
889                                      silc_server_backup_connect_primary,
890                                      ctx->sock);
891       } else {
892         /* Nowhere to connect just return the CONNECTED packet */
893         SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
894                         ctx->session));
895
896         /* Send the CONNECTED packet back to the backup router. */
897         packet = silc_buffer_alloc(2);
898         silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
899         silc_buffer_format(packet,
900                            SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
901                            SILC_STR_UI_CHAR(ctx->session),
902                            SILC_STR_END);
903         silc_server_packet_send(server, ctx->sock, 
904                                 SILC_PACKET_RESUME_ROUTER, 0, 
905                                 packet->data, packet->len, FALSE);
906         silc_buffer_free(packet);
907       }
908
909       if (server->server_type == SILC_ROUTER &&
910           (!server->router || 
911            server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
912         protocol->state++;
913       else
914         protocol->state = SILC_PROTOCOL_STATE_END;
915
916       ctx->sessions = silc_realloc(ctx->sessions,
917                                    sizeof(*ctx->sessions) *
918                                    (ctx->sessions_count + 1));
919       ctx->sessions[ctx->sessions_count].session = ctx->session;
920       ctx->sessions_count++;
921     }
922     break;
923
924   case 2:
925     if (ctx->responder == FALSE) {
926       /* Initiator */
927
928       /* We should have received CONNECTED packet */
929       if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
930         SILC_LOG_ERROR(("Bad resume router packet CONNECTED %d", ctx->type));
931         break;
932       }
933
934       SILC_LOG_DEBUG(("Received CONNECTED (session %d)", ctx->session));
935
936       for (i = 0; i < ctx->sessions_count; i++) {
937         if (ctx->sessions[i].session == ctx->session) {
938           ctx->sessions[i].connected = TRUE;
939           break;
940         }
941       }
942
943       for (i = 0; i < ctx->sessions_count; i++) {
944         if (!ctx->sessions[i].connected)
945           return;
946       }
947
948       SILC_LOG_DEBUG(("All sessions has returned CONNECTED packets"));
949       SILC_LOG_DEBUG(("Sending ENDING packet to primary router"));
950
951       /* Send with a timeout */
952       silc_schedule_task_add(server->schedule, 0, 
953                              silc_server_backup_send_resumed,
954                              protocol, 1, 0, SILC_TASK_TIMEOUT,
955                              SILC_TASK_PRI_NORMAL);
956       return;
957     } else {
958       /* Responder */
959
960       /* We should have been received ENDING packet */
961       if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
962         SILC_LOG_ERROR(("Bad resume router packet ENDING %d", ctx->type));
963         break;
964       }
965
966       SILC_LOG_DEBUG(("Received ENDING packet, we are going to resume now"));
967
968       /* This state is received by the primary router but also servers
969          and perhaps other routers so check that if we are the primary
970          router of the cell then start sending RESUMED packets.  If we
971          are normal server or one of those other routers then procede
972          to next state. */
973       if (server->router &&
974           !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
975           silc_server_config_is_primary_route(server)) {
976         /* We'll wait for RESUMED packet */
977         protocol->state = SILC_PROTOCOL_STATE_END;
978         break;
979       }
980
981       /* Switch announced informations to our primary router of using the
982          backup router. */
983       silc_server_local_servers_toggle_enabled(server, TRUE);
984       silc_server_update_servers_by_server(server, ctx->sock->user_data, 
985                                            server->router);
986       silc_server_update_clients_by_server(server, ctx->sock->user_data,
987                                            server->router, TRUE);
988       if (server->server_type == SILC_SERVER)
989         silc_server_update_channels_by_server(server, ctx->sock->user_data, 
990                                               server->router);
991
992       packet = silc_buffer_alloc(2);
993       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
994
995       /* We are the primary router, start sending RESUMED packets. */
996       if (silc_idcache_get_all(server->local_list->servers, &list)) {
997         if (silc_idcache_list_first(list, &id_cache)) {
998           while (id_cache) {
999             server_entry = (SilcServerEntry)id_cache->context;
1000             if (!server_entry || (server_entry == server->id_entry) || 
1001                 !server_entry->connection || !server_entry->data.send_key) {
1002               if (!silc_idcache_list_next(list, &id_cache))
1003                 break;
1004               else
1005                 continue;
1006             }
1007
1008             SILC_LOG_DEBUG(("Sending RESUMED to %s",
1009                             server_entry->server_name));
1010
1011             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1012
1013             /* This connection is performing this protocol too now */
1014             ((SilcSocketConnection)server_entry->connection)->protocol =
1015               protocol;
1016
1017             if (server_entry->server_type == SILC_ROUTER)
1018               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1019             else
1020               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1021             silc_server_packet_send(server, server_entry->connection,
1022                                     SILC_PACKET_RESUME_ROUTER, 0, 
1023                                     packet->data, packet->len, FALSE);
1024
1025             if (!silc_idcache_list_next(list, &id_cache))
1026               break;
1027           }
1028         }
1029
1030         silc_idcache_list_free(list);
1031       }
1032
1033       if (silc_idcache_get_all(server->global_list->servers, &list)) {
1034         if (silc_idcache_list_first(list, &id_cache)) {
1035           while (id_cache) {
1036             server_entry = (SilcServerEntry)id_cache->context;
1037             if (!server_entry || (server_entry == server->id_entry) || 
1038                 !server_entry->connection || !server_entry->data.send_key) {
1039               if (!silc_idcache_list_next(list, &id_cache))
1040                 break;
1041               else
1042                 continue;
1043             }
1044
1045             SILC_LOG_DEBUG(("Sending RESUMED to %s",
1046                             server_entry->server_name));
1047
1048             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1049
1050             /* This connection is performing this protocol too now */
1051             ((SilcSocketConnection)server_entry->connection)->protocol =
1052               protocol;
1053
1054             if (server_entry->server_type == SILC_ROUTER)
1055               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1056             else
1057               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1058             silc_server_packet_send(server, server_entry->connection,
1059                                     SILC_PACKET_RESUME_ROUTER, 0, 
1060                                     packet->data, packet->len, FALSE);
1061
1062             if (!silc_idcache_list_next(list, &id_cache))
1063               break;
1064           }
1065         }
1066
1067         silc_idcache_list_free(list);
1068       }
1069
1070       silc_buffer_free(packet);
1071
1072       SILC_LOG_INFO(("We are now the primary router of our cell again"));
1073       server->wait_backup = FALSE;
1074
1075       /* For us this is the end of this protocol. */
1076       if (protocol->final_callback)
1077         silc_protocol_execute_final(protocol, server->schedule);
1078       else
1079         silc_protocol_free(protocol);
1080     }
1081     break;
1082
1083   case SILC_PROTOCOL_STATE_END:
1084     {
1085       SilcServerEntry router, backup_router;
1086
1087       /* We should have been received RESUMED packet from our primary
1088          router. */
1089       if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1090           ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1091         SILC_LOG_ERROR(("Bad resume router packet RESUMED %d", ctx->type));
1092         break;
1093       }
1094
1095       SILC_LOG_DEBUG(("Received RESUMED from new primary router"));
1096
1097       if (server->backup_router)
1098         server->server_type = SILC_BACKUP_ROUTER;
1099
1100       /* We have now new primary router. All traffic goes there from now on. */
1101       router = (SilcServerEntry)ctx->sock->user_data;
1102       if (silc_server_backup_replaced_get(server, router->id, 
1103                                           &backup_router)) {
1104
1105         if (backup_router == server->router) {
1106           /* We have new primary router now */
1107           server->id_entry->router = router;
1108           server->router = router;
1109           SILC_LOG_INFO(("Switching back to primary router %s",
1110                          server->router->server_name));
1111         } else {
1112           /* We are connected to new primary and now continue using it */
1113           SILC_LOG_INFO(("Resuming the use of primary router %s",
1114                          router->server_name));
1115         }
1116
1117         /* Update the client entries of the backup router to the new 
1118            router */
1119         silc_server_local_servers_toggle_enabled(server, FALSE);
1120         router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1121         silc_server_update_servers_by_server(server, backup_router, router);
1122         silc_server_update_clients_by_server(server, NULL, router, FALSE);
1123         if (server->server_type == SILC_SERVER)
1124           silc_server_update_channels_by_server(server, backup_router, router);
1125         silc_server_backup_replaced_del(server, backup_router);
1126
1127         /* Announce all of our information to the router. */
1128         if (server->server_type == SILC_ROUTER)
1129           silc_server_announce_servers(server, FALSE, ctx->start,
1130                                        router->connection);
1131
1132         /* Announce our clients and channels to the router */
1133         silc_server_announce_clients(server, ctx->start,
1134                                      router->connection);
1135         silc_server_announce_channels(server, ctx->start,
1136                                       router->connection);
1137       }
1138
1139       /* Send notify about primary router going down to local operators */
1140       SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1141                              SILC_NOTIFY_TYPE_NONE,
1142                              ("%s resumed the use of primary router %s",
1143                               server->server_name,
1144                               server->router->server_name));
1145
1146       /* Protocol has ended, call the final callback */
1147       if (protocol->final_callback)
1148         silc_protocol_execute_final(protocol, server->schedule);
1149       else
1150         silc_protocol_free(protocol);
1151     }
1152     break;
1153
1154   case SILC_PROTOCOL_STATE_ERROR:
1155     /* Protocol has ended, call the final callback */
1156     if (protocol->final_callback)
1157       silc_protocol_execute_final(protocol, server->schedule);
1158     else
1159       silc_protocol_free(protocol);
1160     break;
1161
1162   case SILC_PROTOCOL_STATE_FAILURE:
1163     /* Protocol has ended, call the final callback */
1164     SILC_LOG_ERROR(("Error during backup resume: received Failure"));
1165     if (protocol->final_callback)
1166       silc_protocol_execute_final(protocol, server->schedule);
1167     else
1168       silc_protocol_free(protocol);
1169     break;
1170
1171   case SILC_PROTOCOL_STATE_UNKNOWN:
1172     break;
1173   }
1174 }
1175
1176 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1177 {
1178   SilcProtocol protocol = (SilcProtocol)context;
1179   SilcServerBackupProtocolContext ctx = protocol->context;
1180   SilcServer server = ctx->server;
1181   SilcServerEntry server_entry;
1182   SilcSocketConnection sock;
1183   SilcIDCacheList list;
1184   SilcIDCacheEntry id_cache;
1185
1186   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1187       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1188     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1189   }
1190
1191   /* Remove this protocol from all server entries that has it */
1192   if (silc_idcache_get_all(server->local_list->servers, &list)) {
1193     if (silc_idcache_list_first(list, &id_cache)) {
1194       while (id_cache) {
1195         server_entry = (SilcServerEntry)id_cache->context;
1196         sock = (SilcSocketConnection)server_entry->connection;
1197
1198         if (sock->protocol == protocol) {
1199           sock->protocol = NULL;
1200
1201           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1202             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1203         }
1204         
1205         if (!silc_idcache_list_next(list, &id_cache))
1206           break;
1207       }
1208     }
1209     silc_idcache_list_free(list);
1210   }
1211
1212   if (silc_idcache_get_all(server->global_list->servers, &list)) {
1213     if (silc_idcache_list_first(list, &id_cache)) {
1214       while (id_cache) {
1215         server_entry = (SilcServerEntry)id_cache->context;
1216         sock = (SilcSocketConnection)server_entry->connection;
1217
1218         if (sock->protocol == protocol) {
1219           sock->protocol = NULL;
1220
1221           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1222             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1223         }
1224         
1225         if (!silc_idcache_list_next(list, &id_cache))
1226           break;
1227       }
1228     }
1229     silc_idcache_list_free(list);
1230   }
1231
1232   SILC_LOG_DEBUG(("Backup resuming protocol has ended"));
1233
1234   if (ctx->sock->protocol)
1235     ctx->sock->protocol = NULL;
1236   silc_protocol_free(protocol);
1237   silc_free(ctx->sessions);
1238   silc_free(ctx);
1239 }