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;
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;
46 SilcServerBackupReplaced **replaced;
47 uint32 replaced_count;
53 SilcServerEntry server_entry;
54 } SilcServerBackupProtocolSession;
56 /* Backup resuming protocol context */
59 SilcSocketConnection sock;
63 SilcServerBackupProtocolSession *sessions;
64 uint32 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_ne(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_ne(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 SILC_LOG_HEXDUMP(("IP"), server_id->ip.data, 16);
129 SILC_LOG_HEXDUMP(("IP"), server->backup->servers[i].ip.data, 16);
130 if (server->backup->servers[i].server &&
131 !memcmp(&server->backup->servers[i].ip, &server_id->ip.data,
132 sizeof(server_id->ip.data)))
133 return server->backup->servers[i].server;
139 /* Deletes the backup server `server_entry'. */
140 void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry)
144 SILC_LOG_DEBUG(("Start"));
149 for (i = 0; i < server->backup->servers_count; i++) {
150 if (server->backup->servers[i].server == server_entry) {
151 server->backup->servers[i].server = NULL;
157 /* Marks the IP address and port from the `server_id' as being replaced
158 by backup router indicated by the `server'. If the router connects at
159 a later time we can check whether it has been replaced by an backup
162 void silc_server_backup_replaced_add(SilcServer server,
163 SilcServerID *server_id,
164 SilcServerEntry server_entry)
167 SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
169 SILC_LOG_DEBUG(("Start"));
172 server->backup = silc_calloc(1, sizeof(*server->backup));
173 if (!server->backup->replaced) {
174 server->backup->replaced =
175 silc_calloc(1, sizeof(*server->backup->replaced));
176 server->backup->replaced_count = 1;
179 SILC_LOG_DEBUG(("********************************"));
180 SILC_LOG_DEBUG(("Replaced added"));
182 memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
183 //r->port = server_id->port;
184 r->server = server_entry;
186 for (i = 0; i < server->backup->replaced_count; i++) {
187 if (!server->backup->replaced[i]) {
188 server->backup->replaced[i] = r;
193 i = server->backup->replaced_count;
194 server->backup->replaced = silc_realloc(server->backup->replaced,
195 sizeof(*server->backup->replaced) *
197 server->backup->replaced[i] = r;
198 server->backup->replaced_count++;
201 /* Checks whether the IP address and port from the `server_id' has been
202 replaced by an backup router. If it has been then this returns TRUE
203 and the bacup router entry to the `server' pointer if non-NULL. Returns
204 FALSE if the router is not replaced by backup router. */
206 bool silc_server_backup_replaced_get(SilcServer server,
207 SilcServerID *server_id,
208 SilcServerEntry *server_entry)
212 SILC_LOG_DEBUG(("Start"));
214 SILC_LOG_DEBUG(("*************************************"));
216 if (!server->backup || !server->backup->replaced)
219 for (i = 0; i < server->backup->replaced_count; i++) {
220 if (!server->backup->replaced[i])
222 SILC_LOG_HEXDUMP(("IP"), server_id->ip.data, server_id->ip.data_len);
223 SILC_LOG_HEXDUMP(("IP"), server->backup->replaced[i]->ip.data,
224 server->backup->replaced[i]->ip.data_len);
225 if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip.data,
226 sizeof(server_id->ip.data))) {
228 *server_entry = server->backup->replaced[i]->server;
229 SILC_LOG_DEBUG(("REPLACED"));
234 SILC_LOG_DEBUG(("NOT REPLACED"));
238 /* Deletes a replaced host by the set `server_entry. */
240 void silc_server_backup_replaced_del(SilcServer server,
241 SilcServerEntry server_entry)
245 SILC_LOG_DEBUG(("Start"));
247 if (!server->backup || !server->backup->replaced)
250 for (i = 0; i < server->backup->replaced_count; i++) {
251 if (!server->backup->replaced[i])
253 if (server->backup->replaced[i]->server == server_entry) {
254 silc_free(server->backup->replaced[i]);
255 server->backup->replaced[i] = NULL;
261 /* Broadcast the received packet indicated by `packet' to all of our backup
262 routers. All router wide information is passed using broadcast packets.
263 That is why all backup routers need to get this data too. It is expected
264 that the caller already knows that the `packet' is broadcast packet. */
266 void silc_server_backup_broadcast(SilcServer server,
267 SilcSocketConnection sender,
268 SilcPacketContext *packet)
270 SilcServerEntry backup;
271 SilcSocketConnection sock;
273 SilcIDListData idata;
276 if (!server->backup || server->server_type != SILC_ROUTER)
279 SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
281 buffer = packet->buffer;
282 silc_buffer_push(buffer, buffer->data - buffer->head);
284 for (i = 0; i < server->backup->servers_count; i++) {
285 backup = server->backup->servers[i].server;
287 if (!backup || backup->connection == sender ||
288 server->backup->servers[i].local == FALSE)
291 idata = (SilcIDListData)backup;
292 sock = backup->connection;
294 silc_packet_send_prepare(sock, 0, 0, buffer->len);
295 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
296 silc_packet_encrypt(idata->send_key, idata->hmac_send,
297 sock->outbuf, sock->outbuf->len);
299 SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
300 sock->outbuf->data, sock->outbuf->len);
302 /* Now actually send the packet */
303 silc_server_packet_send_real(server, sock, FALSE);
307 /* A generic routine to send data to all backup routers. If the `sender'
308 is provided it will indicate the original sender of the packet and the
309 packet won't be resent to that entity. The `data' is the data that will
310 be assembled to packet context before sending. The packet will be
311 encrypted this function. If the `force_send' is TRUE the data is sent
312 immediately and not put to queue. If `local' is TRUE then the packet
313 will be sent only to local backup routers inside the cell. If false the
314 packet can go from one cell to the other. This function has no effect
315 if there are no any backup routers. */
317 void silc_server_backup_send(SilcServer server,
318 SilcServerEntry sender,
320 SilcPacketFlags flags,
326 SilcServerEntry backup;
327 SilcSocketConnection sock;
330 if (!server->backup || server->server_type != SILC_ROUTER)
333 SILC_LOG_DEBUG(("Start"));
335 for (i = 0; i < server->backup->servers_count; i++) {
336 backup = server->backup->servers[i].server;
340 if (sender == backup)
343 if (local && server->backup->servers[i].local == FALSE)
346 sock = backup->connection;
347 silc_server_packet_send(server, backup->connection, type, flags,
348 data, data_len, force_send);
352 /* Same as silc_server_backup_send but sets a specific Destination ID to
353 the packet. The Destination ID is indicated by the `dst_id' and the
354 ID type `dst_id_type'. For example, packets destined to channels must
355 be sent using this function. */
357 void silc_server_backup_send_dest(SilcServer server,
358 SilcServerEntry sender,
360 SilcPacketFlags flags,
362 SilcIdType dst_id_type,
368 SilcServerEntry backup;
369 SilcSocketConnection sock;
372 if (!server->backup || server->server_type != SILC_ROUTER)
375 SILC_LOG_DEBUG(("Start"));
377 for (i = 0; i < server->backup->servers_count; i++) {
378 backup = server->backup->servers[i].server;
382 if (sender == backup)
385 if (local && server->backup->servers[i].local == FALSE)
388 sock = backup->connection;
389 silc_server_packet_send_dest(server, backup->connection, type, flags,
390 dst_id, dst_id_type, data, data_len,
395 /* Processes incoming RESUME_ROUTER packet. This can give the packet
396 for processing to the protocol handler or allocate new protocol if
397 start command is received. */
399 void silc_server_backup_resume_router(SilcServer server,
400 SilcSocketConnection sock,
401 SilcPacketContext *packet)
406 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
407 sock->type == SILC_SOCKET_TYPE_UNKNOWN)
410 SILC_LOG_DEBUG(("Start"));
412 SILC_LOG_DEBUG(("********************************"));
413 ret = silc_buffer_unformat(packet->buffer,
414 SILC_STR_UI_CHAR(&type),
415 SILC_STR_UI_CHAR(&session),
420 SILC_LOG_DEBUG(("********************************"));
421 /* If the backup resuming protocol is active then process the packet
423 if (sock->protocol && sock->protocol->protocol &&
424 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
425 SilcServerBackupProtocolContext ctx = sock->protocol->context;
430 SILC_LOG_DEBUG(("********************************"));
431 SILC_LOG_DEBUG(("Continuing protocol, type %d", type));
433 if (type != SILC_SERVER_BACKUP_RESUMED &&
434 type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
435 for (i = 0; i < ctx->sessions_count; i++) {
436 if (session == ctx->sessions[i].session) {
437 ctx->session = session;
438 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
443 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
447 SILC_LOG_DEBUG(("Bad resume router packet"));
451 SILC_LOG_DEBUG(("********************************"));
452 /* We don't have protocol active. If we are router and the packet is
453 coming from our primary router then lets check whether it means we've
454 been replaced by an backup router in my cell. This is usually received
455 immediately after we've connected to our primary router. */
457 if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
458 server->router == sock->user_data &&
459 type == SILC_SERVER_BACKUP_REPLACED) {
460 /* We have been replaced by an backup router in our cell. We must
461 mark our primary router connection disabled since we are not allowed
462 to use it at this moment. */
463 SilcIDListData idata = (SilcIDListData)sock->user_data;
465 SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
466 "wait untill backup resuming protocol is executed"));
468 SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
469 idata->status |= SILC_IDLIST_STATUS_DISABLED;
473 SILC_LOG_DEBUG(("********************************"));
474 if (type == SILC_SERVER_BACKUP_START ||
475 type == SILC_SERVER_BACKUP_START_GLOBAL) {
476 /* We have received a start for resuming protocol. */
477 SilcServerBackupProtocolContext proto_ctx;
479 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
480 proto_ctx->server = server;
481 proto_ctx->sock = sock;
482 proto_ctx->responder = TRUE;
483 proto_ctx->type = type;
484 proto_ctx->session = session;
485 proto_ctx->start = time(0);
487 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
489 /* Run the backup resuming protocol */
490 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
491 &sock->protocol, proto_ctx,
492 silc_server_protocol_backup_done);
493 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
495 SILC_LOG_DEBUG(("EEEEEEEEEEEEEEEEEEEEEEEEe"));
498 /* Timeout task callback to connect to remote router */
500 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
502 SilcServerConnection sconn = (SilcServerConnection)context;
503 SilcServer server = sconn->server;
506 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
507 sconn->remote_port));
509 /* Connect to remote host */
510 sock = silc_net_create_connection(server->config->listen_port->local_ip,
514 silc_schedule_task_add(server->schedule, 0,
515 silc_server_backup_connect_to_router,
516 context, 5, 0, SILC_TASK_TIMEOUT,
517 SILC_TASK_PRI_NORMAL);
521 /* Continue with key exchange protocol */
522 silc_server_start_key_exchange(server, sconn, sock);
525 /* Constantly tries to reconnect to a primary router indicated by the
526 `ip' and `port'. The `connected' callback will be called when the
527 connection is created. */
529 void silc_server_backup_reconnect(SilcServer server,
530 const char *ip, uint16 port,
531 SilcServerConnectRouterCallback callback,
534 SilcServerConnection sconn;
536 sconn = silc_calloc(1, sizeof(*sconn));
537 sconn->server = server;
538 sconn->remote_host = strdup(ip);
539 sconn->remote_port = port;
540 sconn->callback = callback;
541 sconn->callback_context = context;
542 silc_schedule_task_add(server->schedule, 0,
543 silc_server_backup_connect_to_router,
544 sconn, 1, 0, SILC_TASK_TIMEOUT,
545 SILC_TASK_PRI_NORMAL);
548 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
550 SilcServerBackupProtocolContext proto_ctx =
551 (SilcServerBackupProtocolContext)context;
552 SilcServer server = proto_ctx->server;
553 SilcSocketConnection sock = proto_ctx->sock;
555 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
557 /* Run the backup resuming protocol */
558 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
559 &sock->protocol, proto_ctx,
560 silc_server_protocol_backup_done);
561 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
564 /* Called when we've established connection back to our primary router
565 when we've acting as backup router and have replaced the primary router
566 in the cell. This function will start the backup resuming protocol. */
568 void silc_server_backup_connected(SilcServer server,
569 SilcServerEntry server_entry,
572 SilcServerBackupProtocolContext proto_ctx;
573 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
575 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
576 proto_ctx->server = server;
577 proto_ctx->sock = sock;
578 proto_ctx->responder = FALSE;
579 proto_ctx->type = SILC_SERVER_BACKUP_START;
580 proto_ctx->start = time(0);
582 /* Start through scheduler */
583 silc_schedule_task_add(server->schedule, 0,
584 silc_server_backup_connected_later,
587 SILC_TASK_PRI_NORMAL);
590 /* Called when normal server has connected to its primary router after
591 backup router has sent the START packet in reusming protocol. We will
592 move the protocol context from the backup router connection to the
595 static void silc_server_backup_connect_primary(SilcServer server,
596 SilcServerEntry server_entry,
599 SilcSocketConnection backup_router = (SilcSocketConnection)context;
600 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
601 SilcIDListData idata = (SilcIDListData)server_entry;
602 SilcServerBackupProtocolContext ctx =
603 (SilcServerBackupProtocolContext)backup_router->protocol->context;
606 SILC_LOG_DEBUG(("Start"));
608 SILC_LOG_DEBUG(("********************************"));
609 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
611 /* Send the CONNECTED packet back to the backup router. */
612 buffer = silc_buffer_alloc(2);
613 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
614 silc_buffer_format(buffer,
615 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
616 SILC_STR_UI_CHAR(ctx->session),
618 silc_server_packet_send(server, backup_router,
619 SILC_PACKET_RESUME_ROUTER, 0,
620 buffer->data, buffer->len, FALSE);
621 silc_buffer_free(buffer);
623 /* The primary connection is disabled until it sends the RESUMED packet
625 idata->status |= SILC_IDLIST_STATUS_DISABLED;
627 /* Move this protocol context from this backup router connection to
628 the primary router connection since it will send the subsequent
629 packets in this protocol. We don't talk with backup router
631 sock->protocol = backup_router->protocol;
632 ctx->sock = (SilcSocketConnection)server_entry->connection;
633 backup_router->protocol = NULL;
636 /* Resume protocol with RESUME_ROUTER packet:
638 SILC_PACKET_RESUME_ROUTER:
640 <uint8 type> <uint8 Session ID>
642 <type> = the protocol opcode
643 <Session ID> = Identifier for this packet and any subsequent reply
644 packets must include this identifier.
648 1 = To router: Comensing backup resuming protocol. This will
649 indicate that the sender is backup router acting as primary
650 and the receiver is primary router that has been replaced by
653 To server. Comensing backup resuming protocol. This will
654 indicate that the sender is backup router and the receiver
655 must reconnect to the real primary router of the cell.
657 2 = To Router: Comesning backup resuming protocol in another
658 cell. The receiver will connect to its primary router
659 (the router that is now online again) but will not use
660 the link. If the receiver is not configured to connect
661 to any router it does as locally configured. The sender
662 is always backup router.
664 To server: this is never sent to server.
666 3 = To backup router: Sender is normal server or router and it
667 tells to backup router that they have connected to the
668 primary router. Backup router never sends this type.
670 4 = To router: Ending backup resuming protocol. This is sent
671 to the real primary router to tell that it can take over
672 the task as being primary router.
674 To server: same as sending for router.
676 Backup router sends this also to the primary route but only
677 after it has sent them to normal servers and has purged all
678 traffic coming from normal servers.
680 5 = To router: Sender is the real primary router after it has
681 received type 4 from backup router. To tell that it is again
682 primary router of the cell.
684 20 = To router: This is sent only when router is connecting to
685 another router and has been replaced by an backup router.
686 The sender knows that the connectee has been replaced.
690 /* Backup resuming protocol. This protocol is executed when the primary
691 router wants to resume its position as being primary router. */
693 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
695 SilcProtocol protocol = (SilcProtocol)context;
696 SilcServerBackupProtocolContext ctx = protocol->context;
697 SilcServer server = ctx->server;
699 SilcIDCacheList list;
700 SilcIDCacheEntry id_cache;
701 SilcServerEntry server_entry;
704 SILC_LOG_DEBUG(("Start"));
706 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
707 protocol->state = SILC_PROTOCOL_STATE_START;
709 SILC_LOG_DEBUG(("State=%d", protocol->state));
711 switch(protocol->state) {
712 case SILC_PROTOCOL_STATE_START:
713 if (ctx->responder == FALSE) {
714 /* Initiator of the protocol. We are backup router */
716 packet = silc_buffer_alloc(2);
717 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
719 SILC_LOG_DEBUG(("********************************"));
720 SILC_LOG_DEBUG(("Sending START packets"));
722 /* Send the START packet to primary router and normal servers. */
723 if (silc_idcache_get_all(server->local_list->servers, &list)) {
724 if (silc_idcache_list_first(list, &id_cache)) {
726 server_entry = (SilcServerEntry)id_cache->context;
727 if ((server_entry == server->id_entry) ||
728 !server_entry->connection) {
729 if (!silc_idcache_list_next(list, &id_cache))
735 ctx->sessions = silc_realloc(ctx->sessions,
736 sizeof(*ctx->sessions) *
737 (ctx->sessions_count + 1));
738 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
739 ctx->sessions[ctx->sessions_count].connected = FALSE;
740 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
742 SILC_LOG_DEBUG(("********************************"));
743 SILC_LOG_DEBUG(("START for session %d", ctx->sessions_count));
745 /* This connection is performing this protocol too now */
746 ((SilcSocketConnection)server_entry->connection)->protocol =
749 if (server_entry->server_type == SILC_ROUTER)
750 packet->data[0] = SILC_SERVER_BACKUP_START;
752 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
753 packet->data[1] = ctx->sessions_count;
754 silc_server_packet_send(server, server_entry->connection,
755 SILC_PACKET_RESUME_ROUTER, 0,
756 packet->data, packet->len, FALSE);
757 ctx->sessions_count++;
759 if (!silc_idcache_list_next(list, &id_cache))
764 silc_idcache_list_free(list);
767 silc_buffer_free(packet);
769 /* If we are router then announce our possible servers. */
770 if (server->server_type == SILC_ROUTER)
771 silc_server_announce_servers(server, FALSE, 0, ctx->sock);
772 silc_server_announce_clients(server, 0, ctx->sock);
773 silc_server_announce_channels(server, 0, ctx->sock);
777 /* Responder of the protocol. */
778 SilcServerConfigSectionServerConnection *primary;
780 /* We should have received START or START_GLOBAL packet */
781 if (ctx->type != SILC_SERVER_BACKUP_START &&
782 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
783 SILC_LOG_DEBUG(("Bad resume router packet"));
787 SILC_LOG_DEBUG(("********************************"));
788 SILC_LOG_DEBUG(("Received START packet, reconnecting to router"));
790 /* Connect to the primary router that was down that is now supposed
791 to be back online. We send the CONNECTED packet after we've
792 established the connection to the primary router. */
793 primary = silc_server_config_get_primary_router(server->config);
794 if (primary && server->backup_primary) {
795 silc_server_backup_reconnect(server,
796 primary->host, primary->port,
797 silc_server_backup_connect_primary,
800 /* Nowhere to connect just return the CONNECTED packet */
802 SILC_LOG_DEBUG(("********************************"));
803 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
805 /* Send the CONNECTED packet back to the backup router. */
806 packet = silc_buffer_alloc(2);
807 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
808 silc_buffer_format(packet,
809 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
810 SILC_STR_UI_CHAR(ctx->session),
812 silc_server_packet_send(server, ctx->sock,
813 SILC_PACKET_RESUME_ROUTER, 0,
814 packet->data, packet->len, FALSE);
815 silc_buffer_free(packet);
818 if (server->server_type == SILC_ROUTER &&
820 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
823 protocol->state = SILC_PROTOCOL_STATE_END;
825 ctx->sessions = silc_realloc(ctx->sessions,
826 sizeof(*ctx->sessions) *
827 (ctx->sessions_count + 1));
828 ctx->sessions[ctx->sessions_count].session = ctx->session;
829 ctx->sessions_count++;
834 if (ctx->responder == FALSE) {
837 /* We should have received CONNECTED packet */
838 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
839 SILC_LOG_DEBUG(("Bad resume router packet"));
843 SILC_LOG_DEBUG(("********************************"));
844 SILC_LOG_DEBUG(("Received CONNECTED packet, session %d", ctx->session));
846 for (i = 0; i < ctx->sessions_count; i++) {
847 if (ctx->sessions[i].session == ctx->session) {
848 ctx->sessions[i].connected = TRUE;
853 for (i = 0; i < ctx->sessions_count; i++) {
854 if (!ctx->sessions[i].connected)
858 SILC_LOG_DEBUG(("********************************"));
859 SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
861 for (i = 0; i < ctx->sessions_count; i++)
862 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
863 ctx->session = ctx->sessions[i].session;
865 /* We've received all the CONNECTED packets and now we'll send the
866 ENDING packet to the new primary router. */
867 packet = silc_buffer_alloc(2);
868 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
869 silc_buffer_format(packet,
870 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
871 SILC_STR_UI_CHAR(ctx->session),
873 silc_server_packet_send(server, ctx->sock,
874 SILC_PACKET_RESUME_ROUTER, 0,
875 packet->data, packet->len, FALSE);
876 silc_buffer_free(packet);
878 protocol->state = SILC_PROTOCOL_STATE_END;
882 /* We should have been received ENDING packet */
883 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
884 SILC_LOG_DEBUG(("Bad resume router packet"));
888 SILC_LOG_DEBUG(("********************************"));
889 SILC_LOG_DEBUG(("Received ENDING packet, sending RESUMED packets"));
891 /* This state is received by the primary router but also servers
892 and perhaps other routers so check that if we are the primary
893 router of the cell then start sending RESUMED packets. If we
894 are normal server or one of those other routers then procede
896 if (server->router &&
897 !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
898 silc_server_config_is_primary_route(server->config)) {
899 /* We'll wait for RESUMED packet */
900 protocol->state = SILC_PROTOCOL_STATE_END;
904 /* Switch announced informations to our entry instead of using the
906 silc_server_update_clients_by_server(server, ctx->sock->user_data,
907 server->id_entry, TRUE, FALSE);
909 packet = silc_buffer_alloc(2);
910 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
912 /* We are the primary router, start sending RESUMED packets. */
913 if (silc_idcache_get_all(server->local_list->servers, &list)) {
914 if (silc_idcache_list_first(list, &id_cache)) {
916 server_entry = (SilcServerEntry)id_cache->context;
917 if ((server_entry == server->id_entry) ||
918 !server_entry->connection) {
919 if (!silc_idcache_list_next(list, &id_cache))
925 SILC_LOG_DEBUG(("********************************"));
926 SILC_LOG_DEBUG(("RESUMED packet"));
928 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
930 /* This connection is performing this protocol too now */
931 ((SilcSocketConnection)server_entry->connection)->protocol =
934 if (server_entry->server_type == SILC_ROUTER)
935 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
937 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
938 silc_server_packet_send(server, server_entry->connection,
939 SILC_PACKET_RESUME_ROUTER, 0,
940 packet->data, packet->len, FALSE);
942 if (!silc_idcache_list_next(list, &id_cache))
947 silc_idcache_list_free(list);
950 silc_buffer_free(packet);
952 /* For us this is the end of this protocol. */
953 if (protocol->final_callback)
954 silc_protocol_execute_final(protocol, server->schedule);
956 silc_protocol_free(protocol);
960 case SILC_PROTOCOL_STATE_END:
962 SilcIDListData idata;
963 SilcServerEntry primary;
964 SilcServerEntry backup_router;
966 /* We should have been received RESUMED packet from our primary
968 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
969 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
970 SILC_LOG_DEBUG(("Bad resume router packet"));
974 SILC_LOG_DEBUG(("********************************"));
975 SILC_LOG_DEBUG(("Received RESUMED packet"));
977 /* We have now new primary router. All traffic goes there from now on. */
978 if (server->backup_router)
979 server->server_type = SILC_BACKUP_ROUTER;
981 primary = (SilcServerEntry)ctx->sock->user_data;
982 if (silc_server_backup_replaced_get(server, primary->id,
985 if (backup_router == server->router) {
986 server->id_entry->router = ctx->sock->user_data;
987 server->router = ctx->sock->user_data;
988 SILC_LOG_INFO(("Switching back to primary router %s",
989 server->router->server_name));
990 SILC_LOG_DEBUG(("********************************"));
991 SILC_LOG_DEBUG(("Switching back to primary router %s",
992 server->router->server_name));
993 idata = (SilcIDListData)server->router;
994 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
996 /* Update the client entries of the backup router to the new
998 silc_server_update_clients_by_server(server, backup_router,
999 primary, TRUE, FALSE);
1000 silc_server_backup_replaced_del(server, backup_router);
1001 silc_server_backup_add(server, backup_router,
1002 ((SilcSocketConnection)primary->
1004 ((SilcSocketConnection)primary->
1006 backup_router->server_type != SILC_ROUTER ?
1010 /* Announce all of our information to the new primary router. */
1011 if (server->server_type == SILC_ROUTER)
1012 silc_server_announce_servers(server, FALSE, 0,
1013 server->router->connection);
1015 /* Announce our clients and channels to the router */
1016 silc_server_announce_clients(server, 0,
1017 server->router->connection);
1018 silc_server_announce_channels(server, 0,
1019 server->router->connection);
1022 /* Protocol has ended, call the final callback */
1023 if (protocol->final_callback)
1024 silc_protocol_execute_final(protocol, server->schedule);
1026 silc_protocol_free(protocol);
1030 case SILC_PROTOCOL_STATE_ERROR:
1031 /* Protocol has ended, call the final callback */
1032 if (protocol->final_callback)
1033 silc_protocol_execute_final(protocol, server->schedule);
1035 silc_protocol_free(protocol);
1038 case SILC_PROTOCOL_STATE_FAILURE:
1039 /* Protocol has ended, call the final callback */
1040 if (protocol->final_callback)
1041 silc_protocol_execute_final(protocol, server->schedule);
1043 silc_protocol_free(protocol);
1046 case SILC_PROTOCOL_STATE_UNKNOWN:
1051 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1053 SilcProtocol protocol = (SilcProtocol)context;
1054 SilcServerBackupProtocolContext ctx = protocol->context;
1055 SilcServer server = ctx->server;
1056 SilcServerEntry server_entry;
1057 SilcSocketConnection sock;
1058 SilcIDCacheList list;
1059 SilcIDCacheEntry id_cache;
1061 SILC_LOG_DEBUG(("Start"));
1063 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1064 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1065 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1068 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1069 if (silc_idcache_list_first(list, &id_cache)) {
1071 server_entry = (SilcServerEntry)id_cache->context;
1072 sock = (SilcSocketConnection)server_entry->connection;
1074 if (sock->protocol && sock->protocol->protocol &&
1075 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP)
1076 sock->protocol = NULL;
1078 if (!silc_idcache_list_next(list, &id_cache))
1082 silc_idcache_list_free(list);
1085 if (ctx->sock->protocol)
1086 ctx->sock->protocol = NULL;
1087 silc_protocol_free(protocol);
1088 silc_free(ctx->sessions);