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