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(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 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, idata->psn_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)
404 SilcServerBackupProtocolContext ctx;
407 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
408 sock->type == SILC_SOCKET_TYPE_UNKNOWN)
411 SILC_LOG_DEBUG(("Start"));
413 ret = silc_buffer_unformat(packet->buffer,
414 SILC_STR_UI_CHAR(&type),
415 SILC_STR_UI_CHAR(&session),
420 /* Activate the protocol for this socket if necessary */
421 if ((type == SILC_SERVER_BACKUP_RESUMED ||
422 type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
423 sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol &&
424 ((SilcIDListData)sock->user_data)->status &
425 SILC_IDLIST_STATUS_DISABLED) {
426 SilcServerEntry backup_router;
428 if (silc_server_backup_replaced_get(server,
429 ((SilcServerEntry)sock->
432 SilcSocketConnection bsock =
433 (SilcSocketConnection)backup_router->connection;
434 if (bsock->protocol && bsock->protocol->protocol &&
435 bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
436 sock->protocol = bsock->protocol;
437 ctx = sock->protocol->context;
443 /* If the backup resuming protocol is active then process the packet
445 if (sock->protocol && sock->protocol->protocol &&
446 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
447 ctx = sock->protocol->context;
450 SILC_LOG_DEBUG(("********************************"));
451 SILC_LOG_DEBUG(("Continuing protocol, type %d", type));
453 if (type != SILC_SERVER_BACKUP_RESUMED &&
454 type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
455 for (i = 0; i < ctx->sessions_count; i++) {
456 if (session == ctx->sessions[i].session) {
457 ctx->session = session;
458 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
463 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
467 SILC_LOG_DEBUG(("Bad resume router packet"));
471 /* We don't have protocol active. If we are router and the packet is
472 coming from our primary router then lets check whether it means we've
473 been replaced by an backup router in my cell. This is usually received
474 immediately after we've connected to our primary router. */
476 if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
477 server->router == sock->user_data &&
478 type == SILC_SERVER_BACKUP_REPLACED) {
479 /* We have been replaced by an backup router in our cell. We must
480 mark our primary router connection disabled since we are not allowed
481 to use it at this moment. */
482 SilcIDListData idata = (SilcIDListData)sock->user_data;
484 SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
485 "wait until backup resuming protocol is executed"));
487 SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
488 idata->status |= SILC_IDLIST_STATUS_DISABLED;
492 if (type == SILC_SERVER_BACKUP_START ||
493 type == SILC_SERVER_BACKUP_START_GLOBAL) {
494 /* We have received a start for resuming protocol. */
495 SilcServerBackupProtocolContext proto_ctx;
497 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
498 proto_ctx->server = server;
499 proto_ctx->sock = sock;
500 proto_ctx->responder = TRUE;
501 proto_ctx->type = type;
502 proto_ctx->session = session;
503 proto_ctx->start = time(0);
505 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
507 /* Run the backup resuming protocol */
508 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
509 &sock->protocol, proto_ctx,
510 silc_server_protocol_backup_done);
511 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
515 /* Timeout task callback to connect to remote router */
517 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
519 SilcServerConnection sconn = (SilcServerConnection)context;
520 SilcServer server = sconn->server;
523 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
524 sconn->remote_port));
526 /* Connect to remote host */
527 sock = silc_net_create_connection(server->config->server_info->server_ip,
531 silc_schedule_task_add(server->schedule, 0,
532 silc_server_backup_connect_to_router,
533 context, 5, 0, SILC_TASK_TIMEOUT,
534 SILC_TASK_PRI_NORMAL);
538 /* Continue with key exchange protocol */
539 silc_server_start_key_exchange(server, sconn, sock);
542 /* Constantly tries to reconnect to a primary router indicated by the
543 `ip' and `port'. The `connected' callback will be called when the
544 connection is created. */
546 void silc_server_backup_reconnect(SilcServer server,
547 const char *ip, uint16 port,
548 SilcServerConnectRouterCallback callback,
551 SilcServerConnection sconn;
553 sconn = silc_calloc(1, sizeof(*sconn));
554 sconn->server = server;
555 sconn->remote_host = strdup(ip);
556 sconn->remote_port = port;
557 sconn->callback = callback;
558 sconn->callback_context = context;
559 silc_schedule_task_add(server->schedule, 0,
560 silc_server_backup_connect_to_router,
561 sconn, 1, 0, SILC_TASK_TIMEOUT,
562 SILC_TASK_PRI_NORMAL);
565 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
567 SilcServerBackupProtocolContext proto_ctx =
568 (SilcServerBackupProtocolContext)context;
569 SilcServer server = proto_ctx->server;
570 SilcSocketConnection sock = proto_ctx->sock;
572 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
574 /* Run the backup resuming protocol */
575 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
576 &sock->protocol, proto_ctx,
577 silc_server_protocol_backup_done);
578 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
581 /* Called when we've established connection back to our primary router
582 when we've acting as backup router and have replaced the primary router
583 in the cell. This function will start the backup resuming protocol. */
585 void silc_server_backup_connected(SilcServer server,
586 SilcServerEntry server_entry,
589 SilcServerBackupProtocolContext proto_ctx;
590 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
592 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
593 proto_ctx->server = server;
594 proto_ctx->sock = sock;
595 proto_ctx->responder = FALSE;
596 proto_ctx->type = SILC_SERVER_BACKUP_START;
597 proto_ctx->start = time(0);
599 /* Start through scheduler */
600 silc_schedule_task_add(server->schedule, 0,
601 silc_server_backup_connected_later,
604 SILC_TASK_PRI_NORMAL);
607 /* Called when normal server has connected to its primary router after
608 backup router has sent the START packet in reusming protocol. We will
609 move the protocol context from the backup router connection to the
612 static void silc_server_backup_connect_primary(SilcServer server,
613 SilcServerEntry server_entry,
616 SilcSocketConnection backup_router = (SilcSocketConnection)context;
617 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
618 SilcIDListData idata = (SilcIDListData)server_entry;
619 SilcServerBackupProtocolContext ctx =
620 (SilcServerBackupProtocolContext)backup_router->protocol->context;
623 SILC_LOG_DEBUG(("Start"));
625 SILC_LOG_DEBUG(("********************************"));
626 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
628 /* Send the CONNECTED packet back to the backup router. */
629 buffer = silc_buffer_alloc(2);
630 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
631 silc_buffer_format(buffer,
632 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
633 SILC_STR_UI_CHAR(ctx->session),
635 silc_server_packet_send(server, backup_router,
636 SILC_PACKET_RESUME_ROUTER, 0,
637 buffer->data, buffer->len, FALSE);
638 silc_buffer_free(buffer);
640 /* The primary connection is disabled until it sends the RESUMED packet
642 idata->status |= SILC_IDLIST_STATUS_DISABLED;
644 /* Move this protocol context from this backup router connection to
645 the primary router connection since it will send the subsequent
646 packets in this protocol. We don't talk with backup router
648 sock->protocol = backup_router->protocol;
649 ctx->sock = (SilcSocketConnection)server_entry->connection;
650 backup_router->protocol = NULL;
653 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
655 SilcProtocol protocol = (SilcProtocol)context;
656 SilcServerBackupProtocolContext ctx = protocol->context;
657 SilcServer server = ctx->server;
661 for (i = 0; i < ctx->sessions_count; i++)
662 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
663 ctx->session = ctx->sessions[i].session;
665 /* We've received all the CONNECTED packets and now we'll send the
666 ENDING packet to the new primary router. */
667 packet = silc_buffer_alloc(2);
668 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
669 silc_buffer_format(packet,
670 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
671 SILC_STR_UI_CHAR(ctx->session),
673 silc_server_packet_send(server, ctx->sock,
674 SILC_PACKET_RESUME_ROUTER, 0,
675 packet->data, packet->len, FALSE);
676 silc_buffer_free(packet);
678 protocol->state = SILC_PROTOCOL_STATE_END;
681 /* Resume protocol with RESUME_ROUTER packet:
683 SILC_PACKET_RESUME_ROUTER:
685 <uint8 type> <uint8 Session ID>
687 <type> = the protocol opcode
688 <Session ID> = Identifier for this packet and any subsequent reply
689 packets must include this identifier.
693 1 = To router: Comensing backup resuming protocol. This will
694 indicate that the sender is backup router acting as primary
695 and the receiver is primary router that has been replaced by
698 To server. Comensing backup resuming protocol. This will
699 indicate that the sender is backup router and the receiver
700 must reconnect to the real primary router of the cell.
702 2 = To Router: Comesning backup resuming protocol in another
703 cell. The receiver will connect to its primary router
704 (the router that is now online again) but will not use
705 the link. If the receiver is not configured to connect
706 to any router it does as locally configured. The sender
707 is always backup router.
709 To server: this is never sent to server.
711 3 = To backup router: Sender is normal server or router and it
712 tells to backup router that they have connected to the
713 primary router. Backup router never sends this type.
715 4 = To router: Ending backup resuming protocol. This is sent
716 to the real primary router to tell that it can take over
717 the task as being primary router.
719 To server: same as sending for router.
721 Backup router sends this also to the primary route but only
722 after it has sent them to normal servers and has purged all
723 traffic coming from normal servers.
725 5 = To router: Sender is the real primary router after it has
726 received type 4 from backup router. To tell that it is again
727 primary router of the cell.
729 20 = To router: This is sent only when router is connecting to
730 another router and has been replaced by an backup router.
731 The sender knows that the connectee has been replaced.
735 /* Backup resuming protocol. This protocol is executed when the primary
736 router wants to resume its position as being primary router. */
738 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
740 SilcProtocol protocol = (SilcProtocol)context;
741 SilcServerBackupProtocolContext ctx = protocol->context;
742 SilcServer server = ctx->server;
744 SilcIDCacheList list;
745 SilcIDCacheEntry id_cache;
746 SilcServerEntry server_entry;
749 SILC_LOG_DEBUG(("Start"));
751 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
752 protocol->state = SILC_PROTOCOL_STATE_START;
754 SILC_LOG_DEBUG(("State=%d", protocol->state));
756 switch(protocol->state) {
757 case SILC_PROTOCOL_STATE_START:
758 if (ctx->responder == FALSE) {
759 /* Initiator of the protocol. We are backup router */
761 packet = silc_buffer_alloc(2);
762 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
764 SILC_LOG_DEBUG(("********************************"));
765 SILC_LOG_DEBUG(("Sending START packets"));
767 /* Send the START packet to primary router and normal servers. */
768 if (silc_idcache_get_all(server->local_list->servers, &list)) {
769 if (silc_idcache_list_first(list, &id_cache)) {
771 server_entry = (SilcServerEntry)id_cache->context;
772 if (!server_entry || (server_entry == server->id_entry) ||
773 !server_entry->connection || !server_entry->data.send_key ||
774 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
775 if (!silc_idcache_list_next(list, &id_cache))
781 ctx->sessions = silc_realloc(ctx->sessions,
782 sizeof(*ctx->sessions) *
783 (ctx->sessions_count + 1));
784 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
785 ctx->sessions[ctx->sessions_count].connected = FALSE;
786 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
788 SILC_LOG_DEBUG(("********************************"));
789 SILC_LOG_DEBUG(("START (local) for session %d",
790 ctx->sessions_count));
792 /* This connection is performing this protocol too now */
793 ((SilcSocketConnection)server_entry->connection)->protocol =
796 if (server_entry->server_type == SILC_ROUTER)
797 packet->data[0] = SILC_SERVER_BACKUP_START;
799 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
800 packet->data[1] = ctx->sessions_count;
801 silc_server_packet_send(server, server_entry->connection,
802 SILC_PACKET_RESUME_ROUTER, 0,
803 packet->data, packet->len, FALSE);
804 ctx->sessions_count++;
806 if (!silc_idcache_list_next(list, &id_cache))
811 silc_idcache_list_free(list);
814 if (silc_idcache_get_all(server->global_list->servers, &list)) {
815 if (silc_idcache_list_first(list, &id_cache)) {
817 server_entry = (SilcServerEntry)id_cache->context;
818 if (!server_entry || (server_entry == server->id_entry) ||
819 !server_entry->connection || !server_entry->data.send_key ||
820 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
821 if (!silc_idcache_list_next(list, &id_cache))
827 ctx->sessions = silc_realloc(ctx->sessions,
828 sizeof(*ctx->sessions) *
829 (ctx->sessions_count + 1));
830 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
831 ctx->sessions[ctx->sessions_count].connected = FALSE;
832 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
834 SILC_LOG_DEBUG(("********************************"));
835 SILC_LOG_DEBUG(("START (global) for session %d",
836 ctx->sessions_count));
838 /* This connection is performing this protocol too now */
839 ((SilcSocketConnection)server_entry->connection)->protocol =
842 if (server_entry->server_type == SILC_ROUTER)
843 packet->data[0] = SILC_SERVER_BACKUP_START;
845 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
846 packet->data[1] = ctx->sessions_count;
847 silc_server_packet_send(server, server_entry->connection,
848 SILC_PACKET_RESUME_ROUTER, 0,
849 packet->data, packet->len, FALSE);
850 ctx->sessions_count++;
852 if (!silc_idcache_list_next(list, &id_cache))
857 silc_idcache_list_free(list);
860 silc_buffer_free(packet);
862 /* Announce all of our information */
863 silc_server_announce_servers(server, TRUE, 0, ctx->sock);
864 silc_server_announce_clients(server, 0, ctx->sock);
865 silc_server_announce_channels(server, 0, ctx->sock);
869 /* Responder of the protocol. */
870 SilcServerConfigSectionRouter *primary;
872 /* We should have received START or START_GLOBAL packet */
873 if (ctx->type != SILC_SERVER_BACKUP_START &&
874 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
875 SILC_LOG_DEBUG(("Bad resume router packet"));
879 SILC_LOG_DEBUG(("********************************"));
880 SILC_LOG_DEBUG(("Received START packet, reconnecting to router"));
882 /* Connect to the primary router that was down that is now supposed
883 to be back online. We send the CONNECTED packet after we've
884 established the connection to the primary router. */
885 primary = silc_server_config_get_primary_router(server);
886 if (primary && server->backup_primary) {
887 silc_server_backup_reconnect(server,
888 primary->host, primary->port,
889 silc_server_backup_connect_primary,
892 /* Nowhere to connect just return the CONNECTED packet */
894 SILC_LOG_DEBUG(("********************************"));
895 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
897 /* Send the CONNECTED packet back to the backup router. */
898 packet = silc_buffer_alloc(2);
899 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
900 silc_buffer_format(packet,
901 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
902 SILC_STR_UI_CHAR(ctx->session),
904 silc_server_packet_send(server, ctx->sock,
905 SILC_PACKET_RESUME_ROUTER, 0,
906 packet->data, packet->len, FALSE);
907 silc_buffer_free(packet);
910 if (server->server_type == SILC_ROUTER &&
912 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
915 protocol->state = SILC_PROTOCOL_STATE_END;
917 ctx->sessions = silc_realloc(ctx->sessions,
918 sizeof(*ctx->sessions) *
919 (ctx->sessions_count + 1));
920 ctx->sessions[ctx->sessions_count].session = ctx->session;
921 ctx->sessions_count++;
926 if (ctx->responder == FALSE) {
929 /* We should have received CONNECTED packet */
930 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
931 SILC_LOG_DEBUG(("Bad resume router packet"));
935 SILC_LOG_DEBUG(("********************************"));
936 SILC_LOG_DEBUG(("Received CONNECTED packet, session %d", ctx->session));
938 for (i = 0; i < ctx->sessions_count; i++) {
939 if (ctx->sessions[i].session == ctx->session) {
940 ctx->sessions[i].connected = TRUE;
945 for (i = 0; i < ctx->sessions_count; i++) {
946 if (!ctx->sessions[i].connected)
950 SILC_LOG_DEBUG(("********************************"));
951 SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
953 /* Send with a timeout */
954 silc_schedule_task_add(server->schedule, 0,
955 silc_server_backup_send_resumed,
956 protocol, 1, 0, SILC_TASK_TIMEOUT,
957 SILC_TASK_PRI_NORMAL);
962 /* We should have been received ENDING packet */
963 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
964 SILC_LOG_DEBUG(("Bad resume router packet"));
968 SILC_LOG_DEBUG(("********************************"));
969 SILC_LOG_DEBUG(("Received ENDING packet, sending RESUMED packets"));
971 /* This state is received by the primary router but also servers
972 and perhaps other routers so check that if we are the primary
973 router of the cell then start sending RESUMED packets. If we
974 are normal server or one of those other routers then procede
976 if (server->router &&
977 !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
978 silc_server_config_is_primary_route(server)) {
979 /* We'll wait for RESUMED packet */
980 protocol->state = SILC_PROTOCOL_STATE_END;
984 /* Switch announced informations to our primary router of using the
986 silc_server_update_servers_by_server(server, ctx->sock->user_data,
988 silc_server_update_clients_by_server(server, ctx->sock->user_data,
989 server->router, TRUE, FALSE);
990 if (server->server_type == SILC_SERVER)
991 silc_server_update_channels_by_server(server, ctx->sock->user_data,
994 packet = silc_buffer_alloc(2);
995 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
997 /* We are the primary router, start sending RESUMED packets. */
998 if (silc_idcache_get_all(server->local_list->servers, &list)) {
999 if (silc_idcache_list_first(list, &id_cache)) {
1001 server_entry = (SilcServerEntry)id_cache->context;
1002 if (!server_entry || (server_entry == server->id_entry) ||
1003 !server_entry->connection || !server_entry->data.send_key) {
1004 if (!silc_idcache_list_next(list, &id_cache))
1010 SILC_LOG_DEBUG(("********************************"));
1011 SILC_LOG_DEBUG(("RESUMED packet (local)"));
1013 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1015 /* This connection is performing this protocol too now */
1016 ((SilcSocketConnection)server_entry->connection)->protocol =
1019 if (server_entry->server_type == SILC_ROUTER)
1020 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1022 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1023 silc_server_packet_send(server, server_entry->connection,
1024 SILC_PACKET_RESUME_ROUTER, 0,
1025 packet->data, packet->len, FALSE);
1027 if (!silc_idcache_list_next(list, &id_cache))
1032 silc_idcache_list_free(list);
1035 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1036 if (silc_idcache_list_first(list, &id_cache)) {
1038 server_entry = (SilcServerEntry)id_cache->context;
1039 if (!server_entry || (server_entry == server->id_entry) ||
1040 !server_entry->connection || !server_entry->data.send_key) {
1041 if (!silc_idcache_list_next(list, &id_cache))
1047 SILC_LOG_DEBUG(("********************************"));
1048 SILC_LOG_DEBUG(("RESUMED packet (global)"));
1050 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1052 /* This connection is performing this protocol too now */
1053 ((SilcSocketConnection)server_entry->connection)->protocol =
1056 if (server_entry->server_type == SILC_ROUTER)
1057 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1059 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1060 silc_server_packet_send(server, server_entry->connection,
1061 SILC_PACKET_RESUME_ROUTER, 0,
1062 packet->data, packet->len, FALSE);
1064 if (!silc_idcache_list_next(list, &id_cache))
1069 silc_idcache_list_free(list);
1072 silc_buffer_free(packet);
1074 SILC_LOG_INFO(("We are now the primary router of our cell again"));
1076 /* For us this is the end of this protocol. */
1077 if (protocol->final_callback)
1078 silc_protocol_execute_final(protocol, server->schedule);
1080 silc_protocol_free(protocol);
1084 case SILC_PROTOCOL_STATE_END:
1086 SilcIDListData idata;
1087 SilcServerEntry router, backup_router;
1089 /* We should have been received RESUMED packet from our primary
1091 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1092 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1093 SILC_LOG_DEBUG(("Bad resume router packet"));
1097 SILC_LOG_DEBUG(("********************************"));
1098 SILC_LOG_DEBUG(("Received RESUMED packet"));
1100 /* We have now new primary router. All traffic goes there from now on. */
1101 if (server->backup_router)
1102 server->server_type = SILC_BACKUP_ROUTER;
1104 router = (SilcServerEntry)ctx->sock->user_data;
1105 if (silc_server_backup_replaced_get(server, router->id,
1108 if (backup_router == server->router) {
1109 server->id_entry->router = router;
1110 server->router = router;
1111 SILC_LOG_INFO(("Switching back to primary router %s",
1112 server->router->server_name));
1113 SILC_LOG_DEBUG(("Switching back to primary router %s",
1114 server->router->server_name));
1115 idata = (SilcIDListData)server->router;
1116 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1118 SILC_LOG_INFO(("Resuming the use of router %s",
1119 router->server_name));
1120 SILC_LOG_DEBUG(("Resuming the use of router %s",
1121 router->server_name));
1122 idata = (SilcIDListData)router;
1123 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1126 /* Update the client entries of the backup router to the new
1128 silc_server_update_servers_by_server(server, backup_router, router);
1129 silc_server_update_clients_by_server(server, backup_router,
1130 router, TRUE, FALSE);
1131 if (server->server_type == SILC_SERVER)
1132 silc_server_update_channels_by_server(server, backup_router, router);
1133 silc_server_backup_replaced_del(server, backup_router);
1134 silc_server_backup_add(server, backup_router,
1135 ctx->sock->ip, ctx->sock->port,
1136 backup_router->server_type != SILC_ROUTER ?
1139 /* Announce all of our information to the router. */
1140 if (server->server_type == SILC_ROUTER)
1141 silc_server_announce_servers(server, FALSE, 0, router->connection);
1143 /* Announce our clients and channels to the router */
1144 silc_server_announce_clients(server, 0, router->connection);
1145 silc_server_announce_channels(server, 0, router->connection);
1148 /* Protocol has ended, call the final callback */
1149 if (protocol->final_callback)
1150 silc_protocol_execute_final(protocol, server->schedule);
1152 silc_protocol_free(protocol);
1156 case SILC_PROTOCOL_STATE_ERROR:
1157 /* Protocol has ended, call the final callback */
1158 if (protocol->final_callback)
1159 silc_protocol_execute_final(protocol, server->schedule);
1161 silc_protocol_free(protocol);
1164 case SILC_PROTOCOL_STATE_FAILURE:
1165 /* Protocol has ended, call the final callback */
1166 if (protocol->final_callback)
1167 silc_protocol_execute_final(protocol, server->schedule);
1169 silc_protocol_free(protocol);
1172 case SILC_PROTOCOL_STATE_UNKNOWN:
1177 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1179 SilcProtocol protocol = (SilcProtocol)context;
1180 SilcServerBackupProtocolContext ctx = protocol->context;
1181 SilcServer server = ctx->server;
1182 SilcServerEntry server_entry;
1183 SilcSocketConnection sock;
1184 SilcIDCacheList list;
1185 SilcIDCacheEntry id_cache;
1187 SILC_LOG_DEBUG(("Start"));
1189 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1190 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1191 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1194 /* Remove this protocol from all server entries that has it */
1195 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1196 if (silc_idcache_list_first(list, &id_cache)) {
1198 server_entry = (SilcServerEntry)id_cache->context;
1199 sock = (SilcSocketConnection)server_entry->connection;
1201 if (sock->protocol == protocol) {
1202 sock->protocol = NULL;
1204 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1205 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1208 if (!silc_idcache_list_next(list, &id_cache))
1212 silc_idcache_list_free(list);
1215 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1216 if (silc_idcache_list_first(list, &id_cache)) {
1218 server_entry = (SilcServerEntry)id_cache->context;
1219 sock = (SilcSocketConnection)server_entry->connection;
1221 if (sock->protocol == protocol) {
1222 sock->protocol = NULL;
1224 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1225 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1228 if (!silc_idcache_list_next(list, &id_cache))
1232 silc_idcache_list_free(list);
1235 if (ctx->sock->protocol)
1236 ctx->sock->protocol = NULL;
1237 silc_protocol_free(protocol);
1238 silc_free(ctx->sessions);