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.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
28 SilcServerEntry server;
30 } SilcServerBackupEntry;
32 /* Holds IP address and port of the primary router that was replaced
37 SilcServerEntry server; /* Backup router that replaced the primary */
38 } SilcServerBackupReplaced;
41 struct SilcServerBackupStruct {
42 SilcServerBackupEntry *servers;
44 SilcServerBackupReplaced **replaced;
45 uint32 replaced_count;
51 SilcServerEntry server_entry;
52 } SilcServerBackupProtocolSession;
54 /* Backup resuming protocol context */
57 SilcSocketConnection sock;
61 SilcServerBackupProtocolSession *sessions;
62 uint32 sessions_count;
64 } *SilcServerBackupProtocolContext;
66 /* Sets the `backup_server' to be one of our backup router. This can be
67 called multiple times to set multiple backup routers. If `local' is
68 TRUE then the `backup_server' is in the local cell, if FALSE it is
69 in some other cell. */
71 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
77 server->backup = silc_calloc(1, sizeof(*server->backup));
79 for (i = 0; i < server->backup->servers_count; i++) {
80 if (!server->backup->servers[i].server) {
81 server->backup->servers[i].server = backup_server;
82 server->backup->servers[i].local = local;
87 i = server->backup->servers_count;
88 server->backup->servers = silc_realloc(server->backup->servers,
89 sizeof(*server->backup->servers) *
91 server->backup->servers[i].server = backup_server;
92 server->backup->servers[i].local = local;
93 server->backup->servers_count++;
96 /* Returns the first backup router context. Returns NULL if we do not have
97 any backup servers. */
99 SilcServerEntry silc_server_backup_get(SilcServer server)
101 SilcServerEntry backup_router;
107 for (i = 0; i < server->backup->servers_count; i++) {
108 if (server->backup->servers[i].server) {
109 backup_router = server->backup->servers[i].server;
110 server->backup->servers[i].server = NULL;
111 return backup_router;
118 /* Deletes the backup server `server_entry. */
120 void silc_server_backup_del(SilcServer server,
121 SilcServerEntry server_entry)
128 for (i = 0; i < server->backup->servers_count; i++) {
129 if (server->backup->servers[i].server == server_entry) {
130 server->backup->servers[i].server = NULL;
136 /* Marks the IP address and port from the `server_id' as being replaced
137 by backup router indicated by the `server'. If the router connects at
138 a later time we can check whether it has been replaced by an backup
141 void silc_server_backup_replaced_add(SilcServer server,
142 SilcServerID *server_id,
143 SilcServerEntry server_entry)
146 SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
149 server->backup = silc_calloc(1, sizeof(*server->backup));
150 if (!server->backup->replaced) {
151 server->backup->replaced =
152 silc_calloc(1, sizeof(*server->backup->replaced));
153 server->backup->replaced_count = 1;
156 SILC_LOG_DEBUG(("********************************"));
157 SILC_LOG_DEBUG(("Replaced added"));
159 memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
160 //r->port = server_id->port;
161 r->server = server_entry;
163 for (i = 0; i < server->backup->replaced_count; i++) {
164 if (!server->backup->replaced[i]) {
165 server->backup->replaced[i] = r;
170 i = server->backup->replaced_count;
171 server->backup->replaced = silc_realloc(server->backup->replaced,
172 sizeof(*server->backup->replaced) *
174 server->backup->replaced[i] = r;
175 server->backup->replaced_count++;
178 /* Checks whether the IP address and port from the `server_id' has been
179 replaced by an backup router. If it has been then this returns TRUE
180 and the bacup router entry to the `server' pointer if non-NULL. Returns
181 FALSE if the router is not replaced by backup router. */
183 bool silc_server_backup_replaced_get(SilcServer server,
184 SilcServerID *server_id,
185 SilcServerEntry *server_entry)
189 SILC_LOG_DEBUG(("***********************************************"));
191 if (!server->backup || !server->backup->replaced)
194 for (i = 0; i < server->backup->replaced_count; i++) {
195 if (!server->backup->replaced[i])
197 SILC_LOG_HEXDUMP(("IP"), server_id->ip.data, server_id->ip.data_len);
198 SILC_LOG_HEXDUMP(("IP"), server->backup->replaced[i]->ip.data,
199 server->backup->replaced[i]->ip.data_len);
200 if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip,
201 sizeof(server_id->ip))) {
203 *server_entry = server->backup->replaced[i]->server;
204 SILC_LOG_DEBUG(("REPLACED"));
209 SILC_LOG_DEBUG(("NOT REPLACED"));
213 /* Deletes a replaced host by the set `server_entry. */
215 void silc_server_backup_replaced_del(SilcServer server,
216 SilcServerEntry server_entry)
220 if (!server->backup || !server->backup->replaced)
223 for (i = 0; i < server->backup->replaced_count; i++) {
224 if (!server->backup->replaced[i])
226 if (server->backup->replaced[i]->server == server_entry) {
227 silc_free(server->backup->replaced[i]);
228 server->backup->replaced[i] = NULL;
234 /* Broadcast the received packet indicated by `packet' to all of our backup
235 routers. All router wide information is passed using broadcast packets.
236 That is why all backup routers need to get this data too. It is expected
237 that the caller already knows that the `packet' is broadcast packet. */
239 void silc_server_backup_broadcast(SilcServer server,
240 SilcSocketConnection sender,
241 SilcPacketContext *packet)
243 SilcServerEntry backup;
244 SilcSocketConnection sock;
246 SilcIDListData idata;
249 if (!server->backup || server->server_type != SILC_ROUTER)
252 SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
254 buffer = packet->buffer;
255 silc_buffer_push(buffer, buffer->data - buffer->head);
257 for (i = 0; i < server->backup->servers_count; i++) {
258 backup = server->backup->servers[i].server;
260 if (!backup || backup->connection == sender ||
261 server->backup->servers[i].local == FALSE)
264 idata = (SilcIDListData)backup;
265 sock = backup->connection;
267 silc_packet_send_prepare(sock, 0, 0, buffer->len);
268 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
269 silc_packet_encrypt(idata->send_key, idata->hmac_send,
270 sock->outbuf, sock->outbuf->len);
272 SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
273 sock->outbuf->data, sock->outbuf->len);
275 /* Now actually send the packet */
276 silc_server_packet_send_real(server, sock, FALSE);
280 /* A generic routine to send data to all backup routers. If the `sender'
281 is provided it will indicate the original sender of the packet and the
282 packet won't be resent to that entity. The `data' is the data that will
283 be assembled to packet context before sending. The packet will be
284 encrypted this function. If the `force_send' is TRUE the data is sent
285 immediately and not put to queue. If `local' is TRUE then the packet
286 will be sent only to local backup routers inside the cell. If false the
287 packet can go from one cell to the other. This function has no effect
288 if there are no any backup routers. */
290 void silc_server_backup_send(SilcServer server,
291 SilcServerEntry sender,
293 SilcPacketFlags flags,
299 SilcServerEntry backup;
300 SilcSocketConnection sock;
303 if (!server->backup || server->server_type != SILC_ROUTER)
306 SILC_LOG_DEBUG(("Start"));
308 for (i = 0; i < server->backup->servers_count; i++) {
309 backup = server->backup->servers[i].server;
313 if (sender == backup)
316 if (local && server->backup->servers[i].local == FALSE)
319 sock = backup->connection;
320 silc_server_packet_send(server, backup->connection, type, flags,
321 data, data_len, force_send);
325 /* Same as silc_server_backup_send but sets a specific Destination ID to
326 the packet. The Destination ID is indicated by the `dst_id' and the
327 ID type `dst_id_type'. For example, packets destined to channels must
328 be sent using this function. */
330 void silc_server_backup_send_dest(SilcServer server,
331 SilcServerEntry sender,
333 SilcPacketFlags flags,
335 SilcIdType dst_id_type,
341 SilcServerEntry backup;
342 SilcSocketConnection sock;
345 if (!server->backup || server->server_type != SILC_ROUTER)
348 SILC_LOG_DEBUG(("Start"));
350 for (i = 0; i < server->backup->servers_count; i++) {
351 backup = server->backup->servers[i].server;
355 if (sender == backup)
358 if (local && server->backup->servers[i].local == FALSE)
361 sock = backup->connection;
362 silc_server_packet_send_dest(server, backup->connection, type, flags,
363 dst_id, dst_id_type, data, data_len,
368 /* Processes incoming RESUME_ROUTER packet. This can give the packet
369 for processing to the protocol handler or allocate new protocol if
370 start command is received. */
372 void silc_server_backup_resume_router(SilcServer server,
373 SilcSocketConnection sock,
374 SilcPacketContext *packet)
379 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
380 sock->type == SILC_SOCKET_TYPE_UNKNOWN)
383 SILC_LOG_DEBUG(("Start"));
385 ret = silc_buffer_unformat(packet->buffer,
386 SILC_STR_UI_CHAR(&type),
387 SILC_STR_UI_CHAR(&session),
392 /* If the backup resuming protocol is active then process the packet
394 if (sock->protocol && sock->protocol->protocol &&
395 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
396 SilcServerBackupProtocolContext ctx = sock->protocol->context;
401 SILC_LOG_DEBUG(("********************************"));
402 SILC_LOG_DEBUG(("Continuing protocol, type %d", type));
404 if (type != SILC_SERVER_BACKUP_RESUMED &&
405 type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
406 for (i = 0; i < ctx->sessions_count; i++) {
407 if (session == ctx->sessions[i].session) {
408 ctx->session = session;
409 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
414 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
418 SILC_LOG_DEBUG(("Bad resume router packet"));
422 /* We don't have protocol active. If we are router and the packet is
423 coming from our primary router then lets check whether it means we've
424 been replaced by an backup router in my cell. This is usually received
425 immediately after we've connected to our primary router. */
427 if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
428 server->router == sock->user_data &&
429 type == SILC_SERVER_BACKUP_REPLACED) {
430 /* We have been replaced by an backup router in our cell. We must
431 mark our primary router connection disabled since we are not allowed
432 to use it at this moment. */
433 SilcIDListData idata = (SilcIDListData)sock->user_data;
435 SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
436 idata->status |= SILC_IDLIST_STATUS_DISABLED;
440 if (type == SILC_SERVER_BACKUP_START ||
441 type == SILC_SERVER_BACKUP_START_GLOBAL) {
442 /* We have received a start for resuming protocol. */
443 SilcServerBackupProtocolContext proto_ctx;
445 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
446 proto_ctx->server = server;
447 proto_ctx->sock = sock;
448 proto_ctx->responder = TRUE;
449 proto_ctx->type = type;
450 proto_ctx->session = session;
451 proto_ctx->start = time(0);
453 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
455 /* Run the backup resuming protocol */
456 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
457 &sock->protocol, proto_ctx,
458 silc_server_protocol_backup_done);
459 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
463 /* Timeout task callback to connect to remote router */
465 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
467 SilcServerConnection sconn = (SilcServerConnection)context;
468 SilcServer server = sconn->server;
471 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
472 sconn->remote_port));
474 /* Connect to remote host */
475 sock = silc_net_create_connection(server->config->listen_port->local_ip,
479 silc_schedule_task_add(server->schedule, 0,
480 silc_server_backup_connect_to_router,
481 context, 2, 0, SILC_TASK_TIMEOUT,
482 SILC_TASK_PRI_NORMAL);
486 /* Continue with key exchange protocol */
487 silc_server_start_key_exchange(server, sconn, sock);
490 /* Constantly tries to reconnect to a primary router indicated by the
491 `ip' and `port'. The `connected' callback will be called when the
492 connection is created. */
494 void silc_server_backup_reconnect(SilcServer server,
495 const char *ip, uint16 port,
496 SilcServerConnectRouterCallback callback,
499 SilcServerConnection sconn;
501 sconn = silc_calloc(1, sizeof(*sconn));
502 sconn->server = server;
503 sconn->remote_host = strdup(ip);
504 sconn->remote_port = port;
505 sconn->callback = callback;
506 sconn->callback_context = context;
507 silc_schedule_task_add(server->schedule, 0,
508 silc_server_backup_connect_to_router,
509 sconn, 2, 0, SILC_TASK_TIMEOUT,
510 SILC_TASK_PRI_NORMAL);
513 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
515 SilcServerBackupProtocolContext proto_ctx =
516 (SilcServerBackupProtocolContext)context;
517 SilcServer server = proto_ctx->server;
518 SilcSocketConnection sock = proto_ctx->sock;
520 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
522 /* Run the backup resuming protocol */
523 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
524 &sock->protocol, proto_ctx,
525 silc_server_protocol_backup_done);
526 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
529 /* Called when we've established connection back to our primary router
530 when we've acting as backup router and have replaced the primary router
531 in the cell. This function will start the backup resuming protocol. */
533 void silc_server_backup_connected(SilcServer server,
534 SilcServerEntry server_entry,
537 SilcServerBackupProtocolContext proto_ctx;
538 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
540 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
541 proto_ctx->server = server;
542 proto_ctx->sock = sock;
543 proto_ctx->responder = FALSE;
544 proto_ctx->type = SILC_SERVER_BACKUP_START;
545 proto_ctx->start = time(0);
547 /* Start through scheduler */
548 silc_schedule_task_add(server->schedule, 0,
549 silc_server_backup_connected_later,
552 SILC_TASK_PRI_NORMAL);
555 /* Called when normal server has connected to its primary router after
556 backup router has sent the START packet in reusming protocol. We will
557 move the protocol context from the backup router connection to the
560 static void silc_server_backup_connect_primary(SilcServer server,
561 SilcServerEntry server_entry,
564 SilcSocketConnection backup_router = (SilcSocketConnection)context;
565 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
566 SilcIDListData idata = (SilcIDListData)server_entry;
567 SilcServerBackupProtocolContext ctx =
568 (SilcServerBackupProtocolContext)backup_router->protocol->context;
571 SILC_LOG_DEBUG(("********************************"));
572 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
574 /* Send the CONNECTED packet back to the backup router. */
575 buffer = silc_buffer_alloc(2);
576 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
577 silc_buffer_format(buffer,
578 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
579 SILC_STR_UI_CHAR(ctx->session),
581 silc_server_packet_send(server, backup_router,
582 SILC_PACKET_RESUME_ROUTER, 0,
583 buffer->data, buffer->len, FALSE);
584 silc_buffer_free(buffer);
586 /* The primary connection is disabled until it sends the RESUMED packet
588 idata->status |= SILC_IDLIST_STATUS_DISABLED;
590 /* Move this protocol context from this backup router connection to
591 the primary router connection since it will send the subsequent
592 packets in this protocol. We don't talk with backup router
594 sock->protocol = backup_router->protocol;
595 ctx->sock = (SilcSocketConnection)server_entry->connection;
596 backup_router->protocol = NULL;
599 /* Resume protocol with RESUME_ROUTER packet:
601 SILC_PACKET_RESUME_ROUTER:
603 <uint8 type> <uint8 Session ID>
605 <type> = the protocol opcode
606 <Session ID> = Identifier for this packet and any subsequent reply
607 packets must include this identifier.
611 1 = To router: Comensing backup resuming protocol. This will
612 indicate that the sender is backup router acting as primary
613 and the receiver is primary router that has been replaced by
616 To server. Comensing backup resuming protocol. This will
617 indicate that the sender is backup router and the receiver
618 must reconnect to the real primary router of the cell.
620 2 = To Router: Comesning backup resuming protocol in another
621 cell. The receiver will connect to its primary router
622 (the router that is now online again) but will not use
623 the link. If the receiver is not configured to connect
624 to any router it does as locally configured. The sender
625 is always backup router.
627 To server: this is never sent to server.
629 3 = To backup router: Sender is normal server or router and it
630 tells to backup router that they have connected to the
631 primary router. Backup router never sends this type.
633 4 = To router: Ending backup resuming protocol. This is sent
634 to the real primary router to tell that it can take over
635 the task as being primary router.
637 To server: same as sending for router.
639 Backup router sends this also to the primary route but only
640 after it has sent them to normal servers and has purged all
641 traffic coming from normal servers.
643 5 = To router: Sender is the real primary router after it has
644 received type 4 from backup router. To tell that it is again
645 primary router of the cell.
647 20 = To router: This is sent only when router is connecting to
648 another router and has been replaced by an backup router.
649 The sender knows that the connectee has been replaced.
653 /* Backup resuming protocol. This protocol is executed when the primary
654 router wants to resume its position as being primary router. */
656 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
658 SilcProtocol protocol = (SilcProtocol)context;
659 SilcServerBackupProtocolContext ctx = protocol->context;
660 SilcServer server = ctx->server;
662 SilcIDCacheList list;
663 SilcIDCacheEntry id_cache;
664 SilcServerEntry server_entry;
667 SILC_LOG_DEBUG(("Start"));
669 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
670 protocol->state = SILC_PROTOCOL_STATE_START;
672 SILC_LOG_DEBUG(("State=%d", protocol->state));
674 switch(protocol->state) {
675 case SILC_PROTOCOL_STATE_START:
676 if (ctx->responder == FALSE) {
677 /* Initiator of the protocol. We are backup router */
679 packet = silc_buffer_alloc(2);
680 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
682 SILC_LOG_DEBUG(("********************************"));
683 SILC_LOG_DEBUG(("Sending START packets"));
685 /* Send the START packet to primary router and normal servers. */
686 if (silc_idcache_get_all(server->local_list->servers, &list)) {
687 if (silc_idcache_list_first(list, &id_cache)) {
689 server_entry = (SilcServerEntry)id_cache->context;
690 if ((server_entry == server->id_entry) ||
691 !server_entry->connection) {
692 if (!silc_idcache_list_next(list, &id_cache))
698 ctx->sessions = silc_realloc(ctx->sessions,
699 sizeof(*ctx->sessions) *
700 (ctx->sessions_count + 1));
701 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
702 ctx->sessions[ctx->sessions_count].connected = FALSE;
703 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
705 SILC_LOG_DEBUG(("********************************"));
706 SILC_LOG_DEBUG(("START for session %d", ctx->sessions_count));
708 /* This connection is performing this protocol too now */
709 ((SilcSocketConnection)server_entry->connection)->protocol =
712 if (server_entry->server_type == SILC_ROUTER)
713 packet->data[0] = SILC_SERVER_BACKUP_START;
715 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
716 packet->data[1] = ctx->sessions_count;
717 silc_server_packet_send(server, server_entry->connection,
718 SILC_PACKET_RESUME_ROUTER, 0,
719 packet->data, packet->len, FALSE);
720 ctx->sessions_count++;
722 if (!silc_idcache_list_next(list, &id_cache))
727 silc_idcache_list_free(list);
730 silc_buffer_free(packet);
732 /* If we are router then announce our possible servers. */
733 if (server->server_type == SILC_ROUTER)
734 silc_server_announce_servers(server, FALSE, 0, ctx->sock);
735 silc_server_announce_clients(server, 0, ctx->sock);
736 silc_server_announce_channels(server, 0, ctx->sock);
740 /* Responder of the protocol. */
741 SilcServerConfigSectionServerConnection *primary;
743 /* We should have received START or START_GLOBAL packet */
744 if (ctx->type != SILC_SERVER_BACKUP_START &&
745 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
746 SILC_LOG_DEBUG(("Bad resume router packet"));
750 SILC_LOG_DEBUG(("********************************"));
751 SILC_LOG_DEBUG(("Received START packet, reconnecting to router"));
753 /* Connect to the primary router that was down that is now supposed
754 to be back online. We send the CONNECTED packet after we've
755 established the connection to the primary router. */
756 primary = silc_server_config_get_primary_router(server->config);
758 silc_server_backup_reconnect(server,
759 primary->host, primary->port,
760 silc_server_backup_connect_primary,
762 if (server->server_type == SILC_ROUTER &&
764 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
767 protocol->state = SILC_PROTOCOL_STATE_END;
770 /* Nowhere to connect just return the CONNECTED packet */
772 SILC_LOG_DEBUG(("********************************"));
773 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
775 /* Send the CONNECTED packet back to the backup router. */
776 packet = silc_buffer_alloc(2);
777 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
778 silc_buffer_format(packet,
779 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
780 SILC_STR_UI_CHAR(ctx->session),
782 silc_server_packet_send(server, ctx->sock,
783 SILC_PACKET_RESUME_ROUTER, 0,
784 packet->data, packet->len, FALSE);
785 silc_buffer_free(packet);
789 ctx->sessions = silc_realloc(ctx->sessions,
790 sizeof(*ctx->sessions) *
791 (ctx->sessions_count + 1));
792 ctx->sessions[ctx->sessions_count].session = ctx->session;
793 ctx->sessions_count++;
798 if (ctx->responder == FALSE) {
801 /* We should have received CONNECTED packet */
802 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
803 SILC_LOG_DEBUG(("Bad resume router packet"));
807 SILC_LOG_DEBUG(("********************************"));
808 SILC_LOG_DEBUG(("Received CONNECTED packet, session %d", ctx->session));
810 for (i = 0; i < ctx->sessions_count; i++) {
811 if (ctx->sessions[i].session == ctx->session) {
812 ctx->sessions[i].connected = TRUE;
817 for (i = 0; i < ctx->sessions_count; i++) {
818 if (!ctx->sessions[i].connected)
822 SILC_LOG_DEBUG(("********************************"));
823 SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
825 for (i = 0; i < ctx->sessions_count; i++)
826 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
827 ctx->session = ctx->sessions[i].session;
829 /* We've received all the CONNECTED packets and now we'll send the
830 ENDING packet to the new primary router. */
831 packet = silc_buffer_alloc(2);
832 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
833 silc_buffer_format(packet,
834 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
835 SILC_STR_UI_CHAR(ctx->session),
837 silc_server_packet_send(server, ctx->sock,
838 SILC_PACKET_RESUME_ROUTER, 0,
839 packet->data, packet->len, FALSE);
840 silc_buffer_free(packet);
842 protocol->state = SILC_PROTOCOL_STATE_END;
846 /* We should have been received ENDING packet */
847 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
848 SILC_LOG_DEBUG(("Bad resume router packet"));
852 SILC_LOG_DEBUG(("********************************"));
853 SILC_LOG_DEBUG(("Received ENDING packet, sending RESUMED packets"));
855 /* This state is received by the primary router but also servers
856 and perhaps other routers so check that if we are the primary
857 router of the cell then start sending RESUMED packets. If we
858 are normal server or one of those other routers then procede
860 if (server->router &&
861 !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
862 silc_server_config_is_primary_route(server->config)) {
863 /* We'll wait for RESUMED packet */
864 protocol->state = SILC_PROTOCOL_STATE_END;
868 /* Switch announced informations to our entry instead of using the
870 silc_server_update_clients_by_server(server, ctx->sock->user_data,
871 server->id_entry, TRUE, FALSE);
873 packet = silc_buffer_alloc(2);
874 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
876 /* We are the primary router, start sending RESUMED packets. */
877 if (silc_idcache_get_all(server->local_list->servers, &list)) {
878 if (silc_idcache_list_first(list, &id_cache)) {
880 server_entry = (SilcServerEntry)id_cache->context;
881 if ((server_entry == server->id_entry) ||
882 !server_entry->connection) {
883 if (!silc_idcache_list_next(list, &id_cache))
889 SILC_LOG_DEBUG(("********************************"));
890 SILC_LOG_DEBUG(("RESUMED packet"));
892 /* This connection is performing this protocol too now */
893 ((SilcSocketConnection)server_entry->connection)->protocol =
896 if (server_entry->server_type == SILC_ROUTER)
897 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
899 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
900 silc_server_packet_send(server, server_entry->connection,
901 SILC_PACKET_RESUME_ROUTER, 0,
902 packet->data, packet->len, FALSE);
904 if (!silc_idcache_list_next(list, &id_cache))
909 silc_idcache_list_free(list);
912 silc_buffer_free(packet);
914 /* For us this is the end of this protocol. */
915 if (protocol->final_callback)
916 silc_protocol_execute_final(protocol, server->schedule);
918 silc_protocol_free(protocol);
922 case SILC_PROTOCOL_STATE_END:
924 SilcIDListData idata;
925 SilcServerEntry primary;
926 SilcServerEntry backup_router;
928 /* We should have been received RESUMED packet from our primary
930 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
931 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
932 SILC_LOG_DEBUG(("Bad resume router packet"));
936 SILC_LOG_DEBUG(("********************************"));
937 SILC_LOG_DEBUG(("Received RESUMED packet"));
939 /* We have now new primary router. All traffic goes there from now on. */
940 if (server->backup_router)
941 server->server_type = SILC_BACKUP_ROUTER;
943 primary = (SilcServerEntry)ctx->sock->user_data;
944 if (silc_server_backup_replaced_get(server, primary->id,
947 if (backup_router == server->router) {
948 server->id_entry->router = ctx->sock->user_data;
949 server->router = ctx->sock->user_data;
950 SILC_LOG_INFO(("Switching back to primary router %s",
951 server->router->server_name));
952 SILC_LOG_DEBUG(("********************************"));
953 SILC_LOG_DEBUG(("Switching back to primary router %s",
954 server->router->server_name));
955 idata = (SilcIDListData)server->router;
956 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
958 /* Update the client entries of the backup router to the new
960 silc_server_update_clients_by_server(server, backup_router,
961 primary, TRUE, FALSE);
962 silc_server_backup_replaced_del(server, backup_router);
963 silc_server_backup_add(server, backup_router,
964 backup_router->server_type != SILC_ROUTER ?
968 /* Announce all of our information to the new primary router. */
969 if (server->server_type == SILC_ROUTER)
970 silc_server_announce_servers(server, FALSE, 0,
971 server->router->connection);
973 /* Announce our clients and channels to the router */
974 silc_server_announce_clients(server, 0,
975 server->router->connection);
976 silc_server_announce_channels(server, 0,
977 server->router->connection);
980 /* Protocol has ended, call the final callback */
981 if (protocol->final_callback)
982 silc_protocol_execute_final(protocol, server->schedule);
984 silc_protocol_free(protocol);
988 case SILC_PROTOCOL_STATE_ERROR:
989 /* Protocol has ended, call the final callback */
990 if (protocol->final_callback)
991 silc_protocol_execute_final(protocol, server->schedule);
993 silc_protocol_free(protocol);
996 case SILC_PROTOCOL_STATE_FAILURE:
997 /* Protocol has ended, call the final callback */
998 if (protocol->final_callback)
999 silc_protocol_execute_final(protocol, server->schedule);
1001 silc_protocol_free(protocol);
1004 case SILC_PROTOCOL_STATE_UNKNOWN:
1009 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1011 SilcProtocol protocol = (SilcProtocol)context;
1012 SilcServerBackupProtocolContext ctx = protocol->context;
1013 SilcServer server = ctx->server;
1014 SilcServerEntry server_entry;
1015 SilcSocketConnection sock;
1016 SilcIDCacheList list;
1017 SilcIDCacheEntry id_cache;
1019 SILC_LOG_DEBUG(("Start"));
1021 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1022 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1023 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1026 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1027 if (silc_idcache_list_first(list, &id_cache)) {
1029 server_entry = (SilcServerEntry)id_cache->context;
1030 sock = (SilcSocketConnection)server_entry->connection;
1032 if (sock->protocol && sock->protocol->protocol &&
1033 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP)
1034 sock->protocol = NULL;
1036 if (!silc_idcache_list_next(list, &id_cache))
1040 silc_idcache_list_free(list);
1043 if (ctx->sock->protocol)
1044 ctx->sock->protocol = NULL;
1045 silc_protocol_free(protocol);
1046 silc_free(ctx->sessions);