5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2002 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;
32 } SilcServerBackupEntry;
34 /* Holds IP address and port of the primary router that was replaced
39 SilcServerEntry server; /* Backup router that replaced the primary */
40 } SilcServerBackupReplaced;
43 struct SilcServerBackupStruct {
44 SilcServerBackupEntry *servers;
45 SilcUInt32 servers_count;
46 SilcServerBackupReplaced **replaced;
47 SilcUInt32 replaced_count;
53 SilcServerEntry server_entry;
54 } SilcServerBackupProtocolSession;
56 /* Backup resuming protocol context */
59 SilcSocketConnection sock;
63 SilcServerBackupProtocolSession *sessions;
64 SilcUInt32 sessions_count;
66 } *SilcServerBackupProtocolContext;
68 /* Adds the `backup_server' to be one of our backup router. This can be
69 called multiple times to set multiple backup routers. The `ip' and `port'
70 is the IP and port that the `backup_router' will replace if the `ip'
71 will become unresponsive. If `local' is TRUE then the `backup_server' is
72 in the local cell, if FALSE it is in some other cell. */
74 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
75 const char *ip, int port, bool local)
79 SILC_LOG_DEBUG(("Start"));
85 server->backup = silc_calloc(1, sizeof(*server->backup));
87 for (i = 0; i < server->backup->servers_count; i++) {
88 if (!server->backup->servers[i].server) {
89 server->backup->servers[i].server = backup_server;
90 server->backup->servers[i].local = local;
91 memset(server->backup->servers[i].ip.data, 0,
92 sizeof(server->backup->servers[i].ip.data));
93 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
94 sizeof(server->backup->servers[i].ip.data));
95 //server->backup->servers[i].port = port;
100 i = server->backup->servers_count;
101 server->backup->servers = silc_realloc(server->backup->servers,
102 sizeof(*server->backup->servers) *
104 server->backup->servers[i].server = backup_server;
105 server->backup->servers[i].local = local;
106 memset(server->backup->servers[i].ip.data, 0,
107 sizeof(server->backup->servers[i].ip.data));
108 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
109 sizeof(server->backup->servers[i].ip.data));
110 //server->backup->servers[i].port = server_id->port;
111 server->backup->servers_count++;
114 /* Returns backup router for IP and port in `replacing' or NULL if there
115 does not exist backup router. */
117 SilcServerEntry silc_server_backup_get(SilcServer server,
118 SilcServerID *server_id)
122 SILC_LOG_DEBUG(("Start"));
127 for (i = 0; i < server->backup->servers_count; i++) {
128 if (server->backup->servers[i].server &&
129 !memcmp(&server->backup->servers[i].ip, &server_id->ip.data,
130 sizeof(server_id->ip.data)))
131 return server->backup->servers[i].server;
137 /* Deletes the backup server `server_entry'. */
139 void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry)
146 for (i = 0; i < server->backup->servers_count; i++) {
147 if (server->backup->servers[i].server == server_entry) {
148 SILC_LOG_DEBUG(("Removing %s as backup router",
149 server_entry->server_name ? server_entry->server_name :
151 server->backup->servers[i].server = NULL;
152 memset(server->backup->servers[i].ip.data, 0,
153 sizeof(server->backup->servers[i].ip.data));
158 /* Marks the IP address and port from the `server_id' as being replaced
159 by backup router indicated by the `server'. If the router connects at
160 a later time we can check whether it has been replaced by an backup
163 void silc_server_backup_replaced_add(SilcServer server,
164 SilcServerID *server_id,
165 SilcServerEntry server_entry)
168 SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
170 SILC_LOG_DEBUG(("Start"));
173 server->backup = silc_calloc(1, sizeof(*server->backup));
174 if (!server->backup->replaced) {
175 server->backup->replaced =
176 silc_calloc(1, sizeof(*server->backup->replaced));
177 server->backup->replaced_count = 1;
180 SILC_LOG_DEBUG(("********************************"));
181 SILC_LOG_DEBUG(("Replaced added"));
183 memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
184 //r->port = server_id->port;
185 r->server = server_entry;
187 for (i = 0; i < server->backup->replaced_count; i++) {
188 if (!server->backup->replaced[i]) {
189 server->backup->replaced[i] = r;
194 i = server->backup->replaced_count;
195 server->backup->replaced = silc_realloc(server->backup->replaced,
196 sizeof(*server->backup->replaced) *
198 server->backup->replaced[i] = r;
199 server->backup->replaced_count++;
202 /* Checks whether the IP address and port from the `server_id' has been
203 replaced by an backup router. If it has been then this returns TRUE
204 and the bacup router entry to the `server' pointer if non-NULL. Returns
205 FALSE if the router is not replaced by backup router. */
207 bool silc_server_backup_replaced_get(SilcServer server,
208 SilcServerID *server_id,
209 SilcServerEntry *server_entry)
213 SILC_LOG_DEBUG(("Start"));
215 SILC_LOG_DEBUG(("*************************************"));
217 if (!server->backup || !server->backup->replaced)
220 for (i = 0; i < server->backup->replaced_count; i++) {
221 if (!server->backup->replaced[i])
223 SILC_LOG_HEXDUMP(("IP"), server_id->ip.data, server_id->ip.data_len);
224 SILC_LOG_HEXDUMP(("IP"), server->backup->replaced[i]->ip.data,
225 server->backup->replaced[i]->ip.data_len);
226 if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip.data,
227 sizeof(server_id->ip.data))) {
229 *server_entry = server->backup->replaced[i]->server;
230 SILC_LOG_DEBUG(("REPLACED"));
235 SILC_LOG_DEBUG(("NOT REPLACED"));
239 /* Deletes a replaced host by the set `server_entry. */
241 void silc_server_backup_replaced_del(SilcServer server,
242 SilcServerEntry server_entry)
246 SILC_LOG_DEBUG(("Start"));
248 if (!server->backup || !server->backup->replaced)
251 for (i = 0; i < server->backup->replaced_count; i++) {
252 if (!server->backup->replaced[i])
254 if (server->backup->replaced[i]->server == server_entry) {
255 silc_free(server->backup->replaced[i]);
256 server->backup->replaced[i] = NULL;
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. */
267 void silc_server_backup_broadcast(SilcServer server,
268 SilcSocketConnection sender,
269 SilcPacketContext *packet)
271 SilcServerEntry backup;
272 SilcSocketConnection sock;
274 const SilcBufferStruct p;
275 SilcIDListData idata;
278 if (!server->backup || server->server_type != SILC_ROUTER)
281 SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
283 buffer = packet->buffer;
284 silc_buffer_push(buffer, buffer->data - buffer->head);
286 for (i = 0; i < server->backup->servers_count; i++) {
287 backup = server->backup->servers[i].server;
289 if (!backup || backup->connection == sender ||
290 server->backup->servers[i].local == FALSE)
292 if (server->backup->servers[i].server == server->id_entry)
295 idata = (SilcIDListData)backup;
296 sock = backup->connection;
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"));
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);
307 SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len);
309 /* Now actually send the packet */
310 silc_server_packet_send_real(server, sock, FALSE);
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. */
324 void silc_server_backup_send(SilcServer server,
325 SilcServerEntry sender,
327 SilcPacketFlags flags,
333 SilcServerEntry backup;
334 SilcSocketConnection sock;
337 if (!server->backup || server->server_type != SILC_ROUTER)
340 for (i = 0; i < server->backup->servers_count; i++) {
341 backup = server->backup->servers[i].server;
345 if (sender == backup)
348 if (local && server->backup->servers[i].local == FALSE)
350 if (server->backup->servers[i].server == server->id_entry)
353 sock = backup->connection;
355 SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
356 silc_get_packet_name(type), sock->hostname, sock->ip));
358 silc_server_packet_send(server, backup->connection, type, flags,
359 data, data_len, force_send);
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. */
368 void silc_server_backup_send_dest(SilcServer server,
369 SilcServerEntry sender,
371 SilcPacketFlags flags,
373 SilcIdType dst_id_type,
379 SilcServerEntry backup;
380 SilcSocketConnection sock;
383 if (!server->backup || server->server_type != SILC_ROUTER)
386 for (i = 0; i < server->backup->servers_count; i++) {
387 backup = server->backup->servers[i].server;
391 if (sender == backup)
394 if (local && server->backup->servers[i].local == FALSE)
396 if (server->backup->servers[i].server == server->id_entry)
399 sock = backup->connection;
401 SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
402 silc_get_packet_name(type), sock->hostname, sock->ip));
404 silc_server_packet_send_dest(server, backup->connection, type, flags,
405 dst_id, dst_id_type, data, data_len,
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. */
414 void silc_server_backup_resume_router(SilcServer server,
415 SilcSocketConnection sock,
416 SilcPacketContext *packet)
418 SilcUInt8 type, session;
419 SilcServerBackupProtocolContext ctx;
422 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
423 sock->type == SILC_SOCKET_TYPE_UNKNOWN)
426 SILC_LOG_DEBUG(("Start"));
428 ret = silc_buffer_unformat(packet->buffer,
429 SILC_STR_UI_CHAR(&type),
430 SILC_STR_UI_CHAR(&session),
435 /* Activate the protocol for this socket if necessary */
436 if ((type == SILC_SERVER_BACKUP_RESUMED ||
437 type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
438 sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol &&
439 ((SilcIDListData)sock->user_data)->status &
440 SILC_IDLIST_STATUS_DISABLED) {
441 SilcServerEntry backup_router;
443 if (silc_server_backup_replaced_get(server,
444 ((SilcServerEntry)sock->
447 SilcSocketConnection bsock =
448 (SilcSocketConnection)backup_router->connection;
449 if (bsock->protocol && bsock->protocol->protocol &&
450 bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
451 sock->protocol = bsock->protocol;
452 ctx = sock->protocol->context;
458 /* If the backup resuming protocol is active then process the packet
460 if (sock->protocol && sock->protocol->protocol &&
461 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
462 ctx = sock->protocol->context;
465 SILC_LOG_DEBUG(("********************************"));
466 SILC_LOG_DEBUG(("Continuing protocol, type %d", type));
468 if (type != SILC_SERVER_BACKUP_RESUMED &&
469 type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
470 for (i = 0; i < ctx->sessions_count; i++) {
471 if (session == ctx->sessions[i].session) {
472 ctx->session = session;
473 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
478 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
482 SILC_LOG_DEBUG(("Bad resume router packet"));
486 /* We don't have protocol active. If we are router and the packet is
487 coming from our primary router then lets check whether it means we've
488 been replaced by an backup router in my cell. This is usually received
489 immediately after we've connected to our primary router. */
491 if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
492 sock && SILC_PRIMARY_ROUTE(server) == sock &&
493 type == SILC_SERVER_BACKUP_REPLACED) {
494 /* We have been replaced by an backup router in our cell. We must
495 mark our primary router connection disabled since we are not allowed
496 to use it at this moment. */
497 SilcIDListData idata = (SilcIDListData)sock->user_data;
499 SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
500 "wait until backup resuming protocol is executed"));
502 SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
503 idata->status |= SILC_IDLIST_STATUS_DISABLED;
507 if (type == SILC_SERVER_BACKUP_START ||
508 type == SILC_SERVER_BACKUP_START_GLOBAL) {
509 /* We have received a start for resuming protocol. */
510 SilcServerBackupProtocolContext proto_ctx;
512 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
513 proto_ctx->server = server;
514 proto_ctx->sock = sock;
515 proto_ctx->responder = TRUE;
516 proto_ctx->type = type;
517 proto_ctx->session = session;
518 proto_ctx->start = time(0);
520 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
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);
530 /* Timeout task callback to connect to remote router */
532 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
534 SilcServerConnection sconn = (SilcServerConnection)context;
535 SilcServer server = sconn->server;
537 const char *server_ip;
539 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
540 sconn->remote_port));
542 /* Connect to remote host */
543 server_ip = server->config->server_info->primary == NULL ? NULL :
544 server->config->server_info->primary->server_ip;
545 sock = silc_net_create_connection(server_ip, sconn->remote_port,
548 silc_schedule_task_add(server->schedule, 0,
549 silc_server_backup_connect_to_router,
550 context, 5, 0, SILC_TASK_TIMEOUT,
551 SILC_TASK_PRI_NORMAL);
555 /* Continue with key exchange protocol */
556 silc_server_start_key_exchange(server, sconn, sock);
559 /* Constantly tries to reconnect to a primary router indicated by the
560 `ip' and `port'. The `connected' callback will be called when the
561 connection is created. */
563 void silc_server_backup_reconnect(SilcServer server,
564 const char *ip, SilcUInt16 port,
565 SilcServerConnectRouterCallback callback,
568 SilcServerConnection sconn;
570 sconn = silc_calloc(1, sizeof(*sconn));
571 sconn->server = server;
572 sconn->remote_host = strdup(ip);
573 sconn->remote_port = port;
574 sconn->callback = callback;
575 sconn->callback_context = context;
576 silc_schedule_task_add(server->schedule, 0,
577 silc_server_backup_connect_to_router,
578 sconn, 1, 0, SILC_TASK_TIMEOUT,
579 SILC_TASK_PRI_NORMAL);
582 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
584 SilcServerBackupProtocolContext proto_ctx =
585 (SilcServerBackupProtocolContext)context;
586 SilcServer server = proto_ctx->server;
587 SilcSocketConnection sock = proto_ctx->sock;
589 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
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);
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. */
602 void silc_server_backup_connected(SilcServer server,
603 SilcServerEntry server_entry,
606 SilcServerBackupProtocolContext proto_ctx;
607 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
609 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
610 proto_ctx->server = server;
611 proto_ctx->sock = sock;
612 proto_ctx->responder = FALSE;
613 proto_ctx->type = SILC_SERVER_BACKUP_START;
614 proto_ctx->start = time(0);
616 /* Start through scheduler */
617 silc_schedule_task_add(server->schedule, 0,
618 silc_server_backup_connected_later,
621 SILC_TASK_PRI_NORMAL);
624 /* Called when normal server has connected to its primary router after
625 backup router has sent the START packet in reusming protocol. We will
626 move the protocol context from the backup router connection to the
629 static void silc_server_backup_connect_primary(SilcServer server,
630 SilcServerEntry server_entry,
633 SilcSocketConnection backup_router = (SilcSocketConnection)context;
634 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
635 SilcIDListData idata = (SilcIDListData)server_entry;
636 SilcServerBackupProtocolContext ctx =
637 (SilcServerBackupProtocolContext)backup_router->protocol->context;
640 SILC_LOG_DEBUG(("Start"));
642 SILC_LOG_DEBUG(("********************************"));
643 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
645 /* Send the CONNECTED packet back to the backup router. */
646 buffer = silc_buffer_alloc(2);
647 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
648 silc_buffer_format(buffer,
649 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
650 SILC_STR_UI_CHAR(ctx->session),
652 silc_server_packet_send(server, backup_router,
653 SILC_PACKET_RESUME_ROUTER, 0,
654 buffer->data, buffer->len, FALSE);
655 silc_buffer_free(buffer);
657 /* The primary connection is disabled until it sends the RESUMED packet
659 idata->status |= SILC_IDLIST_STATUS_DISABLED;
661 /* Move this protocol context from this backup router connection to
662 the primary router connection since it will send the subsequent
663 packets in this protocol. We don't talk with backup router
665 sock->protocol = backup_router->protocol;
666 ctx->sock = (SilcSocketConnection)server_entry->connection;
667 backup_router->protocol = NULL;
670 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
672 SilcProtocol protocol = (SilcProtocol)context;
673 SilcServerBackupProtocolContext ctx = protocol->context;
674 SilcServer server = ctx->server;
678 for (i = 0; i < ctx->sessions_count; i++)
679 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
680 ctx->session = ctx->sessions[i].session;
682 /* We've received all the CONNECTED packets and now we'll send the
683 ENDING packet to the new primary router. */
684 packet = silc_buffer_alloc(2);
685 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
686 silc_buffer_format(packet,
687 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
688 SILC_STR_UI_CHAR(ctx->session),
690 silc_server_packet_send(server, ctx->sock,
691 SILC_PACKET_RESUME_ROUTER, 0,
692 packet->data, packet->len, FALSE);
693 silc_buffer_free(packet);
695 protocol->state = SILC_PROTOCOL_STATE_END;
698 /* Resume protocol with RESUME_ROUTER packet:
700 SILC_PACKET_RESUME_ROUTER:
702 <SilcUInt8 type> <SilcUInt8 Session ID>
704 <type> = the protocol opcode
705 <Session ID> = Identifier for this packet and any subsequent reply
706 packets must include this identifier.
710 1 = To router: Comensing backup resuming protocol. This will
711 indicate that the sender is backup router acting as primary
712 and the receiver is primary router that has been replaced by
715 To server. Comensing backup resuming protocol. This will
716 indicate that the sender is backup router and the receiver
717 must reconnect to the real primary router of the cell.
719 2 = To Router: Comesning backup resuming protocol in another
720 cell. The receiver will connect to its primary router
721 (the router that is now online again) but will not use
722 the link. If the receiver is not configured to connect
723 to any router it does as locally configured. The sender
724 is always backup router.
726 To server: this is never sent to server.
728 3 = To backup router: Sender is normal server or router and it
729 tells to backup router that they have connected to the
730 primary router. Backup router never sends this type.
732 4 = To router: Ending backup resuming protocol. This is sent
733 to the real primary router to tell that it can take over
734 the task as being primary router.
736 To server: same as sending for router.
738 Backup router sends this also to the primary route but only
739 after it has sent them to normal servers and has purged all
740 traffic coming from normal servers.
742 5 = To router: Sender is the real primary router after it has
743 received type 4 from backup router. To tell that it is again
744 primary router of the cell.
746 20 = To router: This is sent only when router is connecting to
747 another router and has been replaced by an backup router.
748 The sender knows that the connectee has been replaced.
752 /* Backup resuming protocol. This protocol is executed when the primary
753 router wants to resume its position as being primary router. */
755 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
757 SilcProtocol protocol = (SilcProtocol)context;
758 SilcServerBackupProtocolContext ctx = protocol->context;
759 SilcServer server = ctx->server;
761 SilcIDCacheList list;
762 SilcIDCacheEntry id_cache;
763 SilcServerEntry server_entry;
766 SILC_LOG_DEBUG(("Start"));
768 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
769 protocol->state = SILC_PROTOCOL_STATE_START;
771 SILC_LOG_DEBUG(("State=%d", protocol->state));
773 switch(protocol->state) {
774 case SILC_PROTOCOL_STATE_START:
775 if (ctx->responder == FALSE) {
776 /* Initiator of the protocol. We are backup router */
778 packet = silc_buffer_alloc(2);
779 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
781 SILC_LOG_DEBUG(("********************************"));
782 SILC_LOG_DEBUG(("Sending START packets"));
784 /* Send the START packet to primary router and normal servers. */
785 if (silc_idcache_get_all(server->local_list->servers, &list)) {
786 if (silc_idcache_list_first(list, &id_cache)) {
788 server_entry = (SilcServerEntry)id_cache->context;
789 if (!server_entry || (server_entry == server->id_entry) ||
790 !server_entry->connection || !server_entry->data.send_key ||
791 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
792 if (!silc_idcache_list_next(list, &id_cache))
798 ctx->sessions = silc_realloc(ctx->sessions,
799 sizeof(*ctx->sessions) *
800 (ctx->sessions_count + 1));
801 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
802 ctx->sessions[ctx->sessions_count].connected = FALSE;
803 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
805 SILC_LOG_DEBUG(("********************************"));
806 SILC_LOG_DEBUG(("START (local) for session %d",
807 ctx->sessions_count));
809 /* This connection is performing this protocol too now */
810 ((SilcSocketConnection)server_entry->connection)->protocol =
813 if (server_entry->server_type == SILC_ROUTER)
814 packet->data[0] = SILC_SERVER_BACKUP_START;
816 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
817 packet->data[1] = ctx->sessions_count;
818 silc_server_packet_send(server, server_entry->connection,
819 SILC_PACKET_RESUME_ROUTER, 0,
820 packet->data, packet->len, FALSE);
821 ctx->sessions_count++;
823 if (!silc_idcache_list_next(list, &id_cache))
828 silc_idcache_list_free(list);
831 if (silc_idcache_get_all(server->global_list->servers, &list)) {
832 if (silc_idcache_list_first(list, &id_cache)) {
834 server_entry = (SilcServerEntry)id_cache->context;
835 if (!server_entry || (server_entry == server->id_entry) ||
836 !server_entry->connection || !server_entry->data.send_key ||
837 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
838 if (!silc_idcache_list_next(list, &id_cache))
844 ctx->sessions = silc_realloc(ctx->sessions,
845 sizeof(*ctx->sessions) *
846 (ctx->sessions_count + 1));
847 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
848 ctx->sessions[ctx->sessions_count].connected = FALSE;
849 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
851 SILC_LOG_DEBUG(("********************************"));
852 SILC_LOG_DEBUG(("START (global) for session %d",
853 ctx->sessions_count));
855 /* This connection is performing this protocol too now */
856 ((SilcSocketConnection)server_entry->connection)->protocol =
859 if (server_entry->server_type == SILC_ROUTER)
860 packet->data[0] = SILC_SERVER_BACKUP_START;
862 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
863 packet->data[1] = ctx->sessions_count;
864 silc_server_packet_send(server, server_entry->connection,
865 SILC_PACKET_RESUME_ROUTER, 0,
866 packet->data, packet->len, FALSE);
867 ctx->sessions_count++;
869 if (!silc_idcache_list_next(list, &id_cache))
874 silc_idcache_list_free(list);
877 silc_buffer_free(packet);
879 /* Announce all of our information */
880 silc_server_announce_servers(server, TRUE, 0, ctx->sock);
881 silc_server_announce_clients(server, 0, ctx->sock);
882 silc_server_announce_channels(server, 0, ctx->sock);
886 /* Responder of the protocol. */
887 SilcServerConfigRouter *primary;
889 /* We should have received START or START_GLOBAL packet */
890 if (ctx->type != SILC_SERVER_BACKUP_START &&
891 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
892 SILC_LOG_DEBUG(("Bad resume router packet"));
896 SILC_LOG_DEBUG(("********************************"));
897 SILC_LOG_DEBUG(("Received START packet, reconnecting to router"));
899 /* Connect to the primary router that was down that is now supposed
900 to be back online. We send the CONNECTED packet after we've
901 established the connection to the primary router. */
902 primary = silc_server_config_get_primary_router(server);
903 if (primary && server->backup_primary) {
904 silc_server_backup_reconnect(server,
905 primary->host, primary->port,
906 silc_server_backup_connect_primary,
909 /* Nowhere to connect just return the CONNECTED packet */
911 SILC_LOG_DEBUG(("********************************"));
912 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
914 /* Send the CONNECTED packet back to the backup router. */
915 packet = silc_buffer_alloc(2);
916 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
917 silc_buffer_format(packet,
918 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
919 SILC_STR_UI_CHAR(ctx->session),
921 silc_server_packet_send(server, ctx->sock,
922 SILC_PACKET_RESUME_ROUTER, 0,
923 packet->data, packet->len, FALSE);
924 silc_buffer_free(packet);
927 if (server->server_type == SILC_ROUTER &&
929 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
932 protocol->state = SILC_PROTOCOL_STATE_END;
934 ctx->sessions = silc_realloc(ctx->sessions,
935 sizeof(*ctx->sessions) *
936 (ctx->sessions_count + 1));
937 ctx->sessions[ctx->sessions_count].session = ctx->session;
938 ctx->sessions_count++;
943 if (ctx->responder == FALSE) {
946 /* We should have received CONNECTED packet */
947 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
948 SILC_LOG_DEBUG(("Bad resume router packet"));
952 SILC_LOG_DEBUG(("********************************"));
953 SILC_LOG_DEBUG(("Received CONNECTED packet, session %d", ctx->session));
955 for (i = 0; i < ctx->sessions_count; i++) {
956 if (ctx->sessions[i].session == ctx->session) {
957 ctx->sessions[i].connected = TRUE;
962 for (i = 0; i < ctx->sessions_count; i++) {
963 if (!ctx->sessions[i].connected)
967 SILC_LOG_DEBUG(("********************************"));
968 SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
970 /* Send with a timeout */
971 silc_schedule_task_add(server->schedule, 0,
972 silc_server_backup_send_resumed,
973 protocol, 1, 0, SILC_TASK_TIMEOUT,
974 SILC_TASK_PRI_NORMAL);
979 /* We should have been received ENDING packet */
980 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
981 SILC_LOG_DEBUG(("Bad resume router packet"));
985 SILC_LOG_DEBUG(("********************************"));
986 SILC_LOG_DEBUG(("Received ENDING packet, sending RESUMED packets"));
988 /* This state is received by the primary router but also servers
989 and perhaps other routers so check that if we are the primary
990 router of the cell then start sending RESUMED packets. If we
991 are normal server or one of those other routers then procede
993 if (server->router &&
994 !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
995 silc_server_config_is_primary_route(server)) {
996 /* We'll wait for RESUMED packet */
997 protocol->state = SILC_PROTOCOL_STATE_END;
1001 /* Switch announced informations to our primary router of using the
1003 silc_server_update_servers_by_server(server, ctx->sock->user_data,
1004 server->router, TRUE);
1005 silc_server_update_clients_by_server(server, ctx->sock->user_data,
1006 server->router, TRUE, FALSE);
1007 if (server->server_type == SILC_SERVER)
1008 silc_server_update_channels_by_server(server, ctx->sock->user_data,
1011 packet = silc_buffer_alloc(2);
1012 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1014 /* We are the primary router, start sending RESUMED packets. */
1015 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1016 if (silc_idcache_list_first(list, &id_cache)) {
1018 server_entry = (SilcServerEntry)id_cache->context;
1019 if (!server_entry || (server_entry == server->id_entry) ||
1020 !server_entry->connection || !server_entry->data.send_key) {
1021 if (!silc_idcache_list_next(list, &id_cache))
1027 SILC_LOG_DEBUG(("********************************"));
1028 SILC_LOG_DEBUG(("RESUMED packet (local)"));
1030 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1032 /* This connection is performing this protocol too now */
1033 ((SilcSocketConnection)server_entry->connection)->protocol =
1036 if (server_entry->server_type == SILC_ROUTER)
1037 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1039 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1040 silc_server_packet_send(server, server_entry->connection,
1041 SILC_PACKET_RESUME_ROUTER, 0,
1042 packet->data, packet->len, FALSE);
1044 if (!silc_idcache_list_next(list, &id_cache))
1049 silc_idcache_list_free(list);
1052 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1053 if (silc_idcache_list_first(list, &id_cache)) {
1055 server_entry = (SilcServerEntry)id_cache->context;
1056 if (!server_entry || (server_entry == server->id_entry) ||
1057 !server_entry->connection || !server_entry->data.send_key) {
1058 if (!silc_idcache_list_next(list, &id_cache))
1064 SILC_LOG_DEBUG(("********************************"));
1065 SILC_LOG_DEBUG(("RESUMED packet (global)"));
1067 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1069 /* This connection is performing this protocol too now */
1070 ((SilcSocketConnection)server_entry->connection)->protocol =
1073 if (server_entry->server_type == SILC_ROUTER)
1074 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1076 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1077 silc_server_packet_send(server, server_entry->connection,
1078 SILC_PACKET_RESUME_ROUTER, 0,
1079 packet->data, packet->len, FALSE);
1081 if (!silc_idcache_list_next(list, &id_cache))
1086 silc_idcache_list_free(list);
1089 silc_buffer_free(packet);
1091 SILC_LOG_INFO(("We are now the primary router of our cell again"));
1093 /* For us this is the end of this protocol. */
1094 if (protocol->final_callback)
1095 silc_protocol_execute_final(protocol, server->schedule);
1097 silc_protocol_free(protocol);
1101 case SILC_PROTOCOL_STATE_END:
1103 SilcServerEntry router, backup_router;
1105 /* We should have been received RESUMED packet from our primary
1107 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1108 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1109 SILC_LOG_DEBUG(("Bad resume router packet"));
1113 SILC_LOG_DEBUG(("********************************"));
1114 SILC_LOG_DEBUG(("Received RESUMED packet"));
1116 if (server->backup_router)
1117 server->server_type = SILC_BACKUP_ROUTER;
1119 /* We have now new primary router. All traffic goes there from now on. */
1120 router = (SilcServerEntry)ctx->sock->user_data;
1121 if (silc_server_backup_replaced_get(server, router->id,
1124 if (backup_router == server->router) {
1125 /* We have new primary router now */
1126 server->id_entry->router = router;
1127 server->router = router;
1128 server->router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1130 SILC_LOG_INFO(("Switching back to primary router %s",
1131 server->router->server_name));
1133 /* We cannot talk to backup router connection anymore, it's
1134 enabled again if primary goes down. */
1135 backup_router->data.status |= SILC_IDLIST_STATUS_DISABLED;
1137 /* We are connected to new primary and now continue using it */
1138 router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1139 SILC_LOG_INFO(("Resuming the use of primary router %s",
1140 router->server_name));
1143 /* Update the client entries of the backup router to the new
1145 silc_server_update_servers_by_server(server, backup_router, router,
1147 silc_server_update_clients_by_server(server, NULL, router,
1149 if (server->server_type == SILC_SERVER)
1150 silc_server_update_channels_by_server(server, backup_router, router);
1151 silc_server_backup_replaced_del(server, backup_router);
1152 silc_server_backup_add(server, backup_router,
1153 ctx->sock->ip, ctx->sock->port,
1154 backup_router->server_type != SILC_ROUTER ?
1157 /* Announce all of our information to the router. */
1158 if (server->server_type == SILC_ROUTER)
1159 silc_server_announce_servers(server, FALSE, 0, router->connection);
1161 /* Announce our clients and channels to the router */
1162 silc_server_announce_clients(server, 0, router->connection);
1163 silc_server_announce_channels(server, 0, router->connection);
1166 /* Send notify about primary router going down to local operators */
1167 SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1168 SILC_NOTIFY_TYPE_NONE,
1169 ("%s resumed the use of primary router %s",
1170 server->server_name,
1171 server->router->server_name));
1173 /* Protocol has ended, call the final callback */
1174 if (protocol->final_callback)
1175 silc_protocol_execute_final(protocol, server->schedule);
1177 silc_protocol_free(protocol);
1181 case SILC_PROTOCOL_STATE_ERROR:
1182 /* Protocol has ended, call the final callback */
1183 if (protocol->final_callback)
1184 silc_protocol_execute_final(protocol, server->schedule);
1186 silc_protocol_free(protocol);
1189 case SILC_PROTOCOL_STATE_FAILURE:
1190 /* Protocol has ended, call the final callback */
1191 if (protocol->final_callback)
1192 silc_protocol_execute_final(protocol, server->schedule);
1194 silc_protocol_free(protocol);
1197 case SILC_PROTOCOL_STATE_UNKNOWN:
1202 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1204 SilcProtocol protocol = (SilcProtocol)context;
1205 SilcServerBackupProtocolContext ctx = protocol->context;
1206 SilcServer server = ctx->server;
1207 SilcServerEntry server_entry;
1208 SilcSocketConnection sock;
1209 SilcIDCacheList list;
1210 SilcIDCacheEntry id_cache;
1212 SILC_LOG_DEBUG(("Backup resuming protocol is ended"));
1214 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1215 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1216 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1219 /* Remove this protocol from all server entries that has it */
1220 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1221 if (silc_idcache_list_first(list, &id_cache)) {
1223 server_entry = (SilcServerEntry)id_cache->context;
1224 sock = (SilcSocketConnection)server_entry->connection;
1226 if (sock->protocol == protocol) {
1227 sock->protocol = NULL;
1229 SILC_LOG_DEBUG(("***************1 %s:%d",
1230 sock->ip, sock->port));
1232 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1233 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1236 if (!silc_idcache_list_next(list, &id_cache))
1240 silc_idcache_list_free(list);
1243 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1244 if (silc_idcache_list_first(list, &id_cache)) {
1246 server_entry = (SilcServerEntry)id_cache->context;
1247 sock = (SilcSocketConnection)server_entry->connection;
1249 if (sock->protocol == protocol) {
1250 sock->protocol = NULL;
1252 SILC_LOG_DEBUG(("***************2"));
1254 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1255 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1258 if (!silc_idcache_list_next(list, &id_cache))
1262 silc_idcache_list_free(list);
1265 if (ctx->sock->protocol)
1266 ctx->sock->protocol = NULL;
1267 silc_protocol_free(protocol);
1268 silc_free(ctx->sessions);