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