5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 Pekka Riikonen
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.
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.
20 #include "serverincludes.h"
21 #include "server_internal.h"
23 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
27 SilcServerEntry server;
29 } SilcServerBackupEntry;
31 /* Holds IP address and port of the primary router that was replaced
36 SilcServerEntry server; /* Backup router that replaced the primary */
37 } SilcServerBackupReplaced;
40 struct SilcServerBackupStruct {
41 SilcServerBackupEntry *servers;
43 SilcServerBackupReplaced **replaced;
44 uint32 replaced_count;
50 SilcServerEntry server_entry;
51 } SilcServerBackupProtocolSession;
53 /* Backup resuming protocol context */
56 SilcSocketConnection sock;
60 SilcServerBackupProtocolSession *sessions;
61 uint32 sessions_count;
63 } *SilcServerBackupProtocolContext;
65 /* Backup resuming protocol types */
66 #define SILC_SERVER_BACKUP_START 1
67 #define SILC_SERVER_BACKUP_START_GLOBAL 2
68 #define SILC_SERVER_BACKUP_CONNECTED 3
69 #define SILC_SERVER_BACKUP_ENDING 4
70 #define SILC_SERVER_BACKUP_RESUMED 5
71 #define SILC_SERVER_BACKUP_RESUMED_GLOBAL 6
72 #define SILC_SERVER_BACKUP_REPLACED 20
74 /* Sets the `backup_server' to be one of our backup router. This can be
75 called multiple times to set multiple backup routers. If `local' is
76 TRUE then the `backup_server' is in the local cell, if FALSE it is
77 in some other cell. */
79 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
84 if (!server->backup) {
85 server->backup = silc_calloc(1, sizeof(*server->backup));
86 server->backup->servers_count++;
89 for (i = 0; i < server->backup->servers_count; i++) {
90 if (!server->backup->servers[i].server) {
91 server->backup->servers[i].server = backup_server;
92 server->backup->servers[i].local = local;
97 i = server->backup->servers_count;
98 server->backup->servers = silc_realloc(server->backup->servers,
99 sizeof(*server->backup->servers) *
101 server->backup->servers[i].server = backup_server;
102 server->backup->servers[i].local = local;
103 server->backup->servers_count++;
106 /* Returns the first backup router context. Returns NULL if we do not have
107 any backup servers. */
109 SilcServerEntry silc_server_backup_get(SilcServer server)
111 SilcServerEntry backup_router;
117 for (i = 0; i < server->backup->servers_count; i++) {
118 if (server->backup->servers[i].server) {
119 backup_router = server->backup->servers[i].server;
120 server->backup->servers[i].server = NULL;
121 return backup_router;
128 /* Deletes the backup server `server_entry. */
130 void silc_server_backup_del(SilcServer server,
131 SilcServerEntry server_entry)
138 for (i = 0; i < server->backup->servers_count; i++) {
139 if (server->backup->servers[i].server == server_entry) {
140 server->backup->servers[i].server = NULL;
146 /* Marks the IP address and port from the `server_id' as being replaced
147 by backup router indicated by the `server'. If the router connects at
148 a later time we can check whether it has been replaced by an backup
151 void silc_server_backup_replaced_add(SilcServer server,
152 SilcServerID *server_id,
153 SilcServerEntry server_entry)
156 SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
158 if (!server->backup) {
159 server->backup = silc_calloc(1, sizeof(*server->backup));
160 server->backup->servers_count++;
162 if (!server->backup->replaced) {
163 server->backup->replaced =
164 silc_calloc(1, sizeof(*server->backup->replaced));
165 server->backup->replaced_count = 1;
168 memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
169 //r->port = server_id->port;
170 r->server = server_entry;
172 for (i = 0; i < server->backup->replaced_count; i++) {
173 if (!server->backup->replaced[i]) {
174 server->backup->replaced[i] = r;
179 i = server->backup->replaced_count;
180 server->backup->replaced = silc_realloc(server->backup->replaced,
181 sizeof(*server->backup->replaced) *
183 server->backup->replaced[i] = r;
184 server->backup->replaced_count++;
187 /* Checks whether the IP address and port from the `server_id' has been
188 replaced by an backup router. If it has been then this returns TRUE
189 and the bacup router entry to the `server' pointer if non-NULL. Returns
190 FALSE if the router is not replaced by backup router. */
192 bool silc_server_backup_replaced_get(SilcServer server,
193 SilcServerID *server_id,
194 SilcServerEntry *server_entry)
198 if (!server->backup || !server->backup->replaced)
201 for (i = 0; i < server->backup->servers_count; i++) {
202 if (!server->backup->replaced[i])
204 if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip,
205 sizeof(server_id->ip))) {
207 *server_entry = server->backup->replaced[i]->server;
215 /* Deletes the IP address and port from the `server_id' from being replaced
216 by an backup router. */
218 void silc_server_backup_replaced_del(SilcServer server,
219 SilcServerID *server_id)
223 if (!server->backup || !server->backup->replaced)
226 for (i = 0; i < server->backup->servers_count; i++) {
227 if (!server->backup->replaced[i])
229 if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip,
230 sizeof(server_id->ip))) {
231 silc_free(server->backup->replaced[i]);
232 server->backup->replaced[i] = NULL;
238 /* Broadcast the received packet indicated by `packet' to all of our backup
239 routers. All router wide information is passed using broadcast packets.
240 That is why all backup routers need to get this data too. It is expected
241 that the caller already knows that the `packet' is broadcast packet. */
243 void silc_server_backup_broadcast(SilcServer server,
244 SilcSocketConnection sender,
245 SilcPacketContext *packet)
247 SilcServerEntry backup;
248 SilcSocketConnection sock;
250 SilcIDListData idata;
253 if (!server->backup || server->server_type != SILC_ROUTER)
256 SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
258 buffer = packet->buffer;
259 silc_buffer_push(buffer, buffer->data - buffer->head);
261 for (i = 0; i < server->backup->servers_count; i++) {
262 backup = server->backup->servers[i].server;
264 if (!backup || backup->connection == sender ||
265 server->backup->servers[i].local == FALSE)
268 idata = (SilcIDListData)backup;
269 sock = backup->connection;
271 silc_packet_send_prepare(sock, 0, 0, buffer->len);
272 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
273 silc_packet_encrypt(idata->send_key, idata->hmac_send,
274 sock->outbuf, sock->outbuf->len);
276 SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
277 sock->outbuf->data, sock->outbuf->len);
279 /* Now actually send the packet */
280 silc_server_packet_send_real(server, sock, FALSE);
284 /* A generic routine to send data to all backup routers. If the `sender'
285 is provided it will indicate the original sender of the packet and the
286 packet won't be resent to that entity. The `data' is the data that will
287 be assembled to packet context before sending. The packet will be
288 encrypted this function. If the `force_send' is TRUE the data is sent
289 immediately and not put to queue. If `local' is TRUE then the packet
290 will be sent only to local backup routers inside the cell. If false the
291 packet can go from one cell to the other. This function has no effect
292 if there are no any backup routers. */
294 void silc_server_backup_send(SilcServer server,
295 SilcServerEntry sender,
297 SilcPacketFlags flags,
303 SilcServerEntry backup;
304 SilcSocketConnection sock;
307 if (!server->backup || server->server_type != SILC_ROUTER)
310 SILC_LOG_DEBUG(("Start"));
312 for (i = 0; i < server->backup->servers_count; i++) {
313 backup = server->backup->servers[i].server;
317 if (sender == backup)
320 if (local && server->backup->servers[i].local == FALSE)
323 sock = backup->connection;
324 silc_server_packet_send(server, backup->connection, type, flags,
325 data, data_len, force_send);
329 /* Same as silc_server_backup_send but sets a specific Destination ID to
330 the packet. The Destination ID is indicated by the `dst_id' and the
331 ID type `dst_id_type'. For example, packets destined to channels must
332 be sent using this function. */
334 void silc_server_backup_send_dest(SilcServer server,
335 SilcServerEntry sender,
337 SilcPacketFlags flags,
339 SilcIdType dst_id_type,
345 SilcServerEntry backup;
346 SilcSocketConnection sock;
349 if (!server->backup || server->server_type != SILC_ROUTER)
352 SILC_LOG_DEBUG(("Start"));
354 for (i = 0; i < server->backup->servers_count; i++) {
355 backup = server->backup->servers[i].server;
359 if (sender == backup)
362 if (local && server->backup->servers[i].local == FALSE)
365 sock = backup->connection;
366 silc_server_packet_send_dest(server, backup->connection, type, flags,
367 dst_id, dst_id_type, data, data_len,
372 /* Processes incoming RESUME_ROUTER packet. This can give the packet
373 for processing to the protocol handler or allocate new protocol if
374 start command is received. */
376 void silc_server_backup_resume_router(SilcServer server,
377 SilcSocketConnection sock,
378 SilcPacketContext *packet)
383 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
384 sock->type == SILC_SOCKET_TYPE_UNKNOWN)
387 SILC_LOG_DEBUG(("Start"));
389 ret = silc_buffer_unformat(packet->buffer,
390 SILC_STR_UI_CHAR(&type),
391 SILC_STR_UI_CHAR(&session),
396 /* If the backup resuming protocol is active then process the packet
398 if (sock->protocol && sock->protocol->protocol &&
399 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
400 SilcServerBackupProtocolContext ctx = sock->protocol->context;
405 for (i = 0; i < ctx->sessions_count; i++) {
406 if (session == ctx->sessions[i].session) {
407 ctx->session = session;
408 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
413 SILC_LOG_DEBUG(("Bad resume router packet"));
417 /* We don't have protocol active. If we are router and the packet is
418 coming from our primary router then lets check whether it means we've
419 been replaced by an backup router in my cell. This is usually received
420 immediately after we've connected to our primary router. */
422 if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
423 server->router == sock->user_data &&
424 type == SILC_SERVER_BACKUP_REPLACED) {
425 /* We have been replaced by an backup router in our cell. We must
426 mark our primary router connection disabled since we are not allowed
427 to use it at this moment. */
428 SilcIDListData idata = (SilcIDListData)sock->user_data;
430 SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
431 idata->status |= SILC_IDLIST_STATUS_DISABLED;
435 if (type == SILC_SERVER_BACKUP_START ||
436 type == SILC_SERVER_BACKUP_START_GLOBAL) {
437 /* We have received a start for resuming protocol. */
438 SilcServerBackupProtocolContext proto_ctx;
440 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
441 proto_ctx->server = server;
442 proto_ctx->sock = sock;
443 proto_ctx->responder = TRUE;
444 proto_ctx->type = type;
445 proto_ctx->session = session;
446 proto_ctx->start = time(0);
448 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
450 /* Run the backup resuming protocol */
451 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
452 &sock->protocol, proto_ctx,
453 silc_server_protocol_backup_done);
454 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
458 /* Timeout task callback to connect to remote router */
460 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
462 SilcServerConnection sconn = (SilcServerConnection)context;
463 SilcServer server = sconn->server;
466 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
467 sconn->remote_port));
469 /* Connect to remote host */
470 sock = silc_net_create_connection(server->config->listen_port->local_ip,
474 silc_schedule_task_add(server->schedule, 0,
475 silc_server_backup_connect_to_router,
476 context, 0, 2, SILC_TASK_TIMEOUT,
477 SILC_TASK_PRI_NORMAL);
481 /* Continue with key exchange protocol */
482 silc_server_start_key_exchange(server, sconn, sock);
485 /* Constantly tries to reconnect to a primary router indicated by the
486 `ip' and `port'. The `connected' callback will be called when the
487 connection is created. */
489 void silc_server_backup_reconnect(SilcServer server,
490 const char *ip, uint16 port,
491 SilcServerConnectRouterCallback callback,
494 SilcServerConnection sconn;
496 sconn = silc_calloc(1, sizeof(*sconn));
497 sconn->server = server;
498 sconn->remote_host = strdup(ip);
499 sconn->remote_port = port;
500 sconn->callback = callback;
501 sconn->callback_context = context;
502 silc_schedule_task_add(server->schedule, 0,
503 silc_server_backup_connect_to_router,
504 sconn, 2, 0, SILC_TASK_TIMEOUT,
505 SILC_TASK_PRI_NORMAL);
508 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
510 SilcServerBackupProtocolContext proto_ctx =
511 (SilcServerBackupProtocolContext)context;
512 SilcServer server = proto_ctx->server;
513 SilcSocketConnection sock = proto_ctx->sock;
515 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
517 /* Run the backup resuming protocol */
518 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
519 &sock->protocol, proto_ctx,
520 silc_server_protocol_backup_done);
521 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
524 /* Called when we've established connection back to our primary router
525 when we've acting as backup router and have replaced the primary router
526 in the cell. This function will start the backup resuming protocol. */
528 void silc_server_backup_connected(SilcServer server,
529 SilcServerEntry server_entry,
532 SilcServerBackupProtocolContext proto_ctx;
533 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
535 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
536 proto_ctx->server = server;
537 proto_ctx->sock = sock;
538 proto_ctx->responder = FALSE;
539 proto_ctx->type = SILC_SERVER_BACKUP_START;
540 proto_ctx->start = time(0);
542 /* Start through scheduler */
543 silc_schedule_task_add(server->schedule, 0,
544 silc_server_backup_connected_later,
547 SILC_TASK_PRI_NORMAL);
550 /* Called when normal server has connected to its primary router after
551 backup router has sent the START packet in reusming protocol. We will
552 move the protocol context from the backup router connection to the
555 static void silc_server_backup_connect_primary(SilcServer server,
556 SilcServerEntry server_entry,
559 SilcSocketConnection backup_router = (SilcSocketConnection)context;
560 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
561 SilcIDListData idata = (SilcIDListData)server_entry;
562 SilcServerBackupProtocolContext ctx =
563 (SilcServerBackupProtocolContext)backup_router->protocol->context;
566 /* Send the CONNECTED packet back to the backup router. */
567 buffer = silc_buffer_alloc(2);
568 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
569 silc_buffer_format(buffer,
570 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
571 SILC_STR_UI_CHAR(ctx->session),
573 silc_server_packet_send(server, backup_router,
574 SILC_PACKET_RESUME_ROUTER, 0,
575 buffer->data, buffer->len, FALSE);
576 silc_buffer_free(buffer);
578 /* Move this protocol context from this backup router connection to
579 the primary router connection since it will send the subsequent
580 packets in this protocol. We don't talk with backup router
582 sock->protocol = backup_router->protocol;
583 ctx->sock = (SilcSocketConnection)server_entry->connection;
584 backup_router->protocol = NULL;
586 /* The primary connection is disabled until it sends the RESUMED packet
588 idata->status |= SILC_IDLIST_STATUS_DISABLED;
591 /* Resume protocol with RESUME_ROUTER packet:
593 SILC_PACKET_RESUME_ROUTER:
595 <uint8 type> <uint8 Session ID>
597 <type> = the protocol opcode
598 <Session ID> = Identifier for this packet and any subsequent reply
599 packets must include this identifier.
603 1 = To router: Comensing backup resuming protocol. This will
604 indicate that the sender is backup router acting as primary
605 and the receiver is primary router that has been replaced by
608 To server. Comensing backup resuming protocol. This will
609 indicate that the sender is backup router and the receiver
610 must reconnect to the real primary router of the cell.
612 2 = To Router: Comesning backup resuming protocol in another
613 cell. The receiver will connect to its primary router
614 (the router that is now online again) but will not use
615 the link. If the receiver is not configured to connect
616 to any router it does as locally configured. The sender
617 is always backup router.
619 To server: this is never sent to server.
621 3 = To backup router: Sender is normal server or router and it
622 tells to backup router that they have connected to the
623 primary router. Backup router never sends this type.
625 4 = To router: Ending backup resuming protocol. This is sent
626 to the real primary router to tell that it can take over
627 the task as being primary router.
629 To server: same as sending for router.
631 Backup router sends this also to the primary route but only
632 after it has sent them to normal servers and has purged all
633 traffic coming from normal servers.
635 5 = To router: Sender is the real primary router after it has
636 received type 4 from backup router. To tell that it is again
637 primary router of the cell.
639 20 = To router: This is sent only when router is connecting to
640 another router and has been replaced by an backup router.
641 The sender knows that the connectee has been replaced.
645 /* Backup resuming protocol. This protocol is executed when the primary
646 router wants to resume its position as being primary router. */
648 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
650 SilcProtocol protocol = (SilcProtocol)protocol;
651 SilcServerBackupProtocolContext ctx = protocol->context;
652 SilcServer server = ctx->server;
654 SilcIDCacheList list;
655 SilcIDCacheEntry id_cache;
656 SilcServerEntry server_entry;
659 SILC_LOG_DEBUG(("Start"));
661 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
662 protocol->state = SILC_PROTOCOL_STATE_START;
664 SILC_LOG_DEBUG(("State=%d", protocol->state));
666 switch(protocol->state) {
667 case SILC_PROTOCOL_STATE_START:
668 if (ctx->responder == FALSE) {
669 /* Initiator of the protocol. We are backup router */
671 packet = silc_buffer_alloc(2);
672 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
674 /* Send the START packet to primary router and normal servers. */
675 if (silc_idcache_get_all(server->local_list->servers, &list)) {
676 if (silc_idcache_list_first(list, &id_cache)) {
678 server_entry = (SilcServerEntry)id_cache->context;
679 if ((server_entry == server->id_entry) ||
680 !server_entry->connection) {
681 if (!silc_idcache_list_next(list, &id_cache))
687 ctx->sessions = silc_realloc(ctx->sessions,
688 sizeof(*ctx->sessions) *
689 (ctx->sessions_count + 1));
690 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
691 ctx->sessions[ctx->sessions_count].connected = FALSE;
692 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
694 if (server_entry->server_type == SILC_ROUTER)
695 packet->data[0] = SILC_SERVER_BACKUP_START;
697 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
698 packet->data[1] = ctx->sessions_count;
699 silc_server_packet_send(server, server_entry->connection,
700 SILC_PACKET_RESUME_ROUTER, 0,
701 packet->data, packet->len, FALSE);
702 ctx->sessions_count++;
704 if (!silc_idcache_list_next(list, &id_cache))
709 silc_idcache_list_free(list);
712 /* Now, announce all of our information to the primary router */
713 if (server->server_type == SILC_ROUTER)
714 silc_server_announce_servers(server, FALSE, 0);
715 silc_server_announce_clients(server, 0);
716 silc_server_announce_channels(server, 0);
718 silc_buffer_free(packet);
722 /* Responder of the protocol. */
723 SilcServerConfigSectionServerConnection *primary;
725 /* We should have received START or START_GLOBAL packet */
726 if (ctx->type != SILC_SERVER_BACKUP_START &&
727 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
728 SILC_LOG_DEBUG(("Bad resume router packet"));
732 /* Connect to the primary router that was down that is now supposed
733 to be back online. We send the CONNECTED packet after we've
734 established the connection to the primary router. */
735 primary = silc_server_config_get_primary_router(server->config);
737 silc_server_backup_reconnect(server,
738 primary->host, primary->port,
739 silc_server_backup_connect_primary,
747 if (ctx->responder == FALSE) {
750 /* We should have received CONNECTED packet */
751 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
752 SILC_LOG_DEBUG(("Bad resume router packet"));
756 for (i = 0; i < ctx->sessions_count; i++) {
757 if (ctx->sessions[i].session == ctx->session) {
758 ctx->sessions[i].connected = TRUE;
762 for (i = 0; i < ctx->sessions_count; i++) {
763 if (!ctx->sessions[i].connected)
767 /* We've received all the CONNECTED packets and now we'll send the
768 ENDING packet to the new primary router. */
769 packet = silc_buffer_alloc(2);
770 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
771 silc_buffer_format(packet,
772 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
773 SILC_STR_UI_CHAR(ctx->session),
775 silc_server_packet_send(server, ctx->sock,
776 SILC_PACKET_RESUME_ROUTER, 0,
777 packet->data, packet->len, FALSE);
778 silc_buffer_free(packet);
780 protocol->state = SILC_PROTOCOL_STATE_END;
784 /* We should have been received ENDING packet */
785 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
786 SILC_LOG_DEBUG(("Bad resume router packet"));
790 /* This state is received by the primary router but also servers
791 and perhaps other routers so check that if we are the primary
792 router of the cell then start sending RESUMED packets. If we
793 are normal server or one of those other routers then procede
795 if (!(server->router->data.status & SILC_IDLIST_STATUS_DISABLED)) {
796 /* We'll wait for RESUMED packet */
797 protocol->state = SILC_PROTOCOL_STATE_END;
801 packet = silc_buffer_alloc(2);
802 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
804 /* We are the primary router, start sending RESUMED packets. */
805 if (silc_idcache_get_all(server->local_list->servers, &list)) {
806 if (silc_idcache_list_first(list, &id_cache)) {
808 server_entry = (SilcServerEntry)id_cache->context;
809 if ((server_entry == server->id_entry) ||
810 !server_entry->connection) {
811 if (!silc_idcache_list_next(list, &id_cache))
817 if (server_entry->server_type == SILC_ROUTER)
818 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
820 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
821 packet->data[1] = ctx->sessions_count;
822 silc_server_packet_send(server, server_entry->connection,
823 SILC_PACKET_RESUME_ROUTER, 0,
824 packet->data, packet->len, FALSE);
826 if (!silc_idcache_list_next(list, &id_cache))
831 silc_idcache_list_free(list);
834 silc_buffer_free(packet);
836 /* For us this is the end of this protocol. */
837 if (protocol->final_callback)
838 silc_protocol_execute_final(protocol, server->schedule);
840 silc_protocol_free(protocol);
844 case SILC_PROTOCOL_STATE_END:
846 SilcIDListData idata;
847 SilcServerEntry primary;
848 SilcServerEntry backup_router;
850 /* We should have been received RESUMED packet from our primary
852 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
853 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
854 SILC_LOG_DEBUG(("Bad resume router packet"));
858 /* We have now new primary router. All traffic goes there from now on. */
859 if (server->backup_router)
860 server->server_type = SILC_BACKUP_ROUTER;
862 primary = (SilcServerEntry)ctx->sock->user_data;
863 if (silc_server_backup_replaced_get(server, primary->id,
866 if (backup_router == server->router) {
867 server->id_entry->router = ctx->sock->user_data;
868 server->router = ctx->sock->user_data;
869 SILC_LOG_DEBUG(("Switching back to primary router %s",
870 server->router->server_name));
871 idata = (SilcIDListData)server->router;
872 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
875 /* Announce all of our information to the new primary router. We
876 announce all that was updated after the protocol was started since
877 the router knows all the older stuff. */
878 if (server->server_type == SILC_ROUTER)
879 silc_server_announce_servers(server, FALSE, ctx->start - 60);
881 /* Announce our clients and channels to the router */
882 silc_server_announce_clients(server, ctx->start - 60);
883 silc_server_announce_channels(server, ctx->start - 60);
886 /* Protocol has ended, call the final callback */
887 if (protocol->final_callback)
888 silc_protocol_execute_final(protocol, server->schedule);
890 silc_protocol_free(protocol);
894 case SILC_PROTOCOL_STATE_ERROR:
897 case SILC_PROTOCOL_STATE_FAILURE:
900 case SILC_PROTOCOL_STATE_UNKNOWN:
905 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)