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);
25 static void silc_server_backup_connect_primary(SilcServer server,
26 SilcServerEntry server_entry,
31 SilcServerEntry server;
35 } SilcServerBackupEntry;
37 /* Holds IP address and port of the primary router that was replaced
42 SilcServerEntry server; /* Backup router that replaced the primary */
43 } SilcServerBackupReplaced;
46 struct SilcServerBackupStruct {
47 SilcServerBackupEntry *servers;
48 SilcUInt32 servers_count;
49 SilcServerBackupReplaced **replaced;
50 SilcUInt32 replaced_count;
56 SilcServerEntry server_entry;
57 } SilcServerBackupProtocolSession;
59 /* Backup resuming protocol context */
62 SilcSocketConnection sock;
66 SilcServerBackupProtocolSession *sessions;
67 SilcUInt32 sessions_count;
69 } *SilcServerBackupProtocolContext;
71 /* Adds the `backup_server' to be one of our backup router. This can be
72 called multiple times to set multiple backup routers. The `ip' and `port'
73 is the IP and port that the `backup_router' will replace if the `ip'
74 will become unresponsive. If `local' is TRUE then the `backup_server' is
75 in the local cell, if FALSE it is in some other cell. */
77 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
78 const char *ip, int port, bool local)
85 if (!server->backup) {
86 server->backup = silc_calloc(1, sizeof(*server->backup));
91 SILC_LOG_DEBUG(("Backup router %s will replace %s",
92 ((SilcSocketConnection)backup_server->connection)->ip,
95 for (i = 0; i < server->backup->servers_count; i++) {
96 if (!server->backup->servers[i].server) {
97 server->backup->servers[i].server = backup_server;
98 server->backup->servers[i].local = local;
99 memset(server->backup->servers[i].ip.data, 0,
100 sizeof(server->backup->servers[i].ip.data));
101 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
102 sizeof(server->backup->servers[i].ip.data));
107 i = server->backup->servers_count;
108 server->backup->servers = silc_realloc(server->backup->servers,
109 sizeof(*server->backup->servers) *
111 server->backup->servers[i].server = backup_server;
112 server->backup->servers[i].local = local;
113 memset(server->backup->servers[i].ip.data, 0,
114 sizeof(server->backup->servers[i].ip.data));
115 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
116 sizeof(server->backup->servers[i].ip.data));
117 server->backup->servers_count++;
120 /* Returns backup router for IP and port in `replacing' or NULL if there
121 does not exist backup router. */
123 SilcServerEntry silc_server_backup_get(SilcServer server,
124 SilcServerID *server_id)
131 for (i = 0; i < server->backup->servers_count; i++) {
132 if (server->backup->servers[i].server &&
133 !memcmp(&server->backup->servers[i].ip, &server_id->ip.data,
134 sizeof(server_id->ip.data))) {
135 SILC_LOG_DEBUG(("Found backup router %s for %s",
136 server->backup->servers[i].server->server_name,
137 silc_id_render(server_id, SILC_ID_SERVER)));
138 return server->backup->servers[i].server;
145 /* Deletes the backup server `server_entry'. */
147 void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry)
154 for (i = 0; i < server->backup->servers_count; i++) {
155 if (server->backup->servers[i].server == server_entry) {
156 SILC_LOG_DEBUG(("Removing %s as backup router",
157 silc_id_render(server->backup->servers[i].server->id,
159 server->backup->servers[i].server = NULL;
160 memset(server->backup->servers[i].ip.data, 0,
161 sizeof(server->backup->servers[i].ip.data));
166 /* Frees all data allocated for backup routers. Call this after deleting
167 all backup routers and when new routers are added no more, for example
168 when shutting down the server. */
170 void silc_server_backup_free(SilcServer server)
177 /* Delete existing servers if caller didn't do it */
178 for (i = 0; i < server->backup->servers_count; i++) {
179 if (server->backup->servers[i].server)
180 silc_server_backup_del(server, server->backup->servers[i].server);
183 silc_free(server->backup->servers);
184 silc_free(server->backup);
185 server->backup = NULL;
188 /* Marks the IP address and port from the `server_id' as being replaced
189 by backup router indicated by the `server'. If the router connects at
190 a later time we can check whether it has been replaced by an backup
193 void silc_server_backup_replaced_add(SilcServer server,
194 SilcServerID *server_id,
195 SilcServerEntry server_entry)
198 SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
201 server->backup = silc_calloc(1, sizeof(*server->backup));
202 if (!server->backup->replaced) {
203 server->backup->replaced =
204 silc_calloc(1, sizeof(*server->backup->replaced));
205 server->backup->replaced_count = 1;
208 SILC_LOG_DEBUG(("Replacing router %s with %s",
209 silc_id_render(server_id, SILC_ID_SERVER),
210 server_entry->server_name));
212 memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
213 r->server = server_entry;
215 for (i = 0; i < server->backup->replaced_count; i++) {
216 if (!server->backup->replaced[i]) {
217 server->backup->replaced[i] = r;
222 i = server->backup->replaced_count;
223 server->backup->replaced = silc_realloc(server->backup->replaced,
224 sizeof(*server->backup->replaced) *
226 server->backup->replaced[i] = r;
227 server->backup->replaced_count++;
230 /* Checks whether the IP address and port from the `server_id' has been
231 replaced by an backup router. If it has been then this returns TRUE
232 and the bacup router entry to the `server' pointer if non-NULL. Returns
233 FALSE if the router is not replaced by backup router. */
235 bool silc_server_backup_replaced_get(SilcServer server,
236 SilcServerID *server_id,
237 SilcServerEntry *server_entry)
241 if (!server->backup || !server->backup->replaced)
244 for (i = 0; i < server->backup->replaced_count; i++) {
245 if (!server->backup->replaced[i])
247 if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip.data,
248 sizeof(server_id->ip.data))) {
250 *server_entry = server->backup->replaced[i]->server;
251 SILC_LOG_DEBUG(("Router %s is replaced by %s",
252 silc_id_render(server_id, SILC_ID_SERVER),
253 server->backup->replaced[i]->server->server_name));
258 SILC_LOG_DEBUG(("Router %s is not replaced by backup router",
259 silc_id_render(server_id, SILC_ID_SERVER)));
263 /* Deletes a replaced host by the set `server_entry. */
265 void silc_server_backup_replaced_del(SilcServer server,
266 SilcServerEntry server_entry)
270 if (!server->backup || !server->backup->replaced)
273 for (i = 0; i < server->backup->replaced_count; i++) {
274 if (!server->backup->replaced[i])
276 if (server->backup->replaced[i]->server == server_entry) {
277 silc_free(server->backup->replaced[i]);
278 server->backup->replaced[i] = NULL;
284 /* Broadcast the received packet indicated by `packet' to all of our backup
285 routers. All router wide information is passed using broadcast packets.
286 That is why all backup routers need to get this data too. It is expected
287 that the caller already knows that the `packet' is broadcast packet. */
289 void silc_server_backup_broadcast(SilcServer server,
290 SilcSocketConnection sender,
291 SilcPacketContext *packet)
293 SilcServerEntry backup;
294 SilcSocketConnection sock;
296 const SilcBufferStruct p;
297 SilcIDListData idata;
300 if (!server->backup || server->server_type != SILC_ROUTER)
303 SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
305 buffer = packet->buffer;
306 silc_buffer_push(buffer, buffer->data - buffer->head);
308 for (i = 0; i < server->backup->servers_count; i++) {
309 backup = server->backup->servers[i].server;
311 if (!backup || backup->connection == sender ||
312 server->backup->servers[i].local == FALSE)
314 if (server->backup->servers[i].server == server->id_entry)
317 idata = (SilcIDListData)backup;
318 sock = backup->connection;
320 if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
321 (const SilcBuffer)&p)) {
322 SILC_LOG_ERROR(("Cannot send packet"));
325 silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
326 silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
327 (SilcBuffer)&p, p.len);
329 SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len);
331 /* Now actually send the packet */
332 silc_server_packet_send_real(server, sock, FALSE);
336 /* A generic routine to send data to all backup routers. If the `sender'
337 is provided it will indicate the original sender of the packet and the
338 packet won't be resent to that entity. The `data' is the data that will
339 be assembled to packet context before sending. The packet will be
340 encrypted this function. If the `force_send' is TRUE the data is sent
341 immediately and not put to queue. If `local' is TRUE then the packet
342 will be sent only to local backup routers inside the cell. If false the
343 packet can go from one cell to the other. This function has no effect
344 if there are no any backup routers. */
346 void silc_server_backup_send(SilcServer server,
347 SilcServerEntry sender,
349 SilcPacketFlags flags,
355 SilcServerEntry backup;
356 SilcSocketConnection sock;
359 if (!server->backup || server->server_type != SILC_ROUTER)
362 for (i = 0; i < server->backup->servers_count; i++) {
363 backup = server->backup->servers[i].server;
364 if (!backup || sender == backup)
366 if (local && server->backup->servers[i].local == FALSE)
368 if (server->backup->servers[i].server == server->id_entry)
371 sock = backup->connection;
373 SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
374 silc_get_packet_name(type), sock->hostname, sock->ip));
376 silc_server_packet_send(server, backup->connection, type, flags,
377 data, data_len, force_send);
381 /* Same as silc_server_backup_send but sets a specific Destination ID to
382 the packet. The Destination ID is indicated by the `dst_id' and the
383 ID type `dst_id_type'. For example, packets destined to channels must
384 be sent using this function. */
386 void silc_server_backup_send_dest(SilcServer server,
387 SilcServerEntry sender,
389 SilcPacketFlags flags,
391 SilcIdType dst_id_type,
397 SilcServerEntry backup;
398 SilcSocketConnection sock;
401 if (!server->backup || server->server_type != SILC_ROUTER)
404 for (i = 0; i < server->backup->servers_count; i++) {
405 backup = server->backup->servers[i].server;
406 if (!backup || sender == backup)
408 if (local && server->backup->servers[i].local == FALSE)
410 if (server->backup->servers[i].server == server->id_entry)
413 sock = backup->connection;
415 SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
416 silc_get_packet_name(type), sock->hostname, sock->ip));
418 silc_server_packet_send_dest(server, backup->connection, type, flags,
419 dst_id, dst_id_type, data, data_len,
424 /* Processes incoming RESUME_ROUTER packet. This can give the packet
425 for processing to the protocol handler or allocate new protocol if
426 start command is received. */
428 void silc_server_backup_resume_router(SilcServer server,
429 SilcSocketConnection sock,
430 SilcPacketContext *packet)
432 SilcUInt8 type, session;
433 SilcServerBackupProtocolContext ctx;
436 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
437 sock->type == SILC_SOCKET_TYPE_UNKNOWN) {
438 SILC_LOG_DEBUG(("Bad packet received"));
442 ret = silc_buffer_unformat(packet->buffer,
443 SILC_STR_UI_CHAR(&type),
444 SILC_STR_UI_CHAR(&session),
447 SILC_LOG_DEBUG(("Malformed packet received"));
451 /* Activate the protocol for this socket if necessary */
452 if ((type == SILC_SERVER_BACKUP_RESUMED ||
453 type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
454 sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol &&
455 ((SilcIDListData)sock->user_data)->status &
456 SILC_IDLIST_STATUS_DISABLED) {
457 SilcServerEntry backup_router;
459 if (silc_server_backup_replaced_get(server,
460 ((SilcServerEntry)sock->
463 SilcSocketConnection bsock =
464 (SilcSocketConnection)backup_router->connection;
465 if (bsock->protocol && bsock->protocol->protocol &&
466 bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
467 sock->protocol = bsock->protocol;
468 ctx = sock->protocol->context;
474 /* If the backup resuming protocol is active then process the packet
476 if (sock->protocol && sock->protocol->protocol &&
477 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
478 ctx = sock->protocol->context;
481 if (type != SILC_SERVER_BACKUP_RESUMED &&
482 type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
483 for (i = 0; i < ctx->sessions_count; i++) {
484 if (session == ctx->sessions[i].session) {
485 ctx->session = session;
486 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
491 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
495 SILC_LOG_DEBUG(("Bad resume router packet"));
499 /* We don't have protocol active. If we are router and the packet is
500 coming from our primary router then lets check whether it means we've
501 been replaced by an backup router in my cell. This is usually received
502 immediately after we've connected to our primary router. */
504 if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
505 sock && SILC_PRIMARY_ROUTE(server) == sock &&
506 type == SILC_SERVER_BACKUP_REPLACED) {
507 /* We have been replaced by an backup router in our cell. We must
508 mark our primary router connection disabled since we are not allowed
509 to use it at this moment. */
510 SilcIDListData idata = (SilcIDListData)sock->user_data;
511 SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
512 "wait until backup resuming protocol is executed"));
513 idata->status |= SILC_IDLIST_STATUS_DISABLED;
517 if (type == SILC_SERVER_BACKUP_START ||
518 type == SILC_SERVER_BACKUP_START_GLOBAL) {
519 /* We have received a start for resuming protocol. */
520 SilcServerBackupProtocolContext proto_ctx;
522 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
523 proto_ctx->server = server;
524 proto_ctx->sock = sock;
525 proto_ctx->responder = TRUE;
526 proto_ctx->type = type;
527 proto_ctx->session = session;
528 proto_ctx->start = time(0);
530 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
532 /* Run the backup resuming protocol */
533 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
534 &sock->protocol, proto_ctx,
535 silc_server_protocol_backup_done);
536 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
540 /* Timeout task callback to connect to remote router */
542 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
544 SilcServerConnection sconn = (SilcServerConnection)context;
545 SilcServer server = sconn->server;
547 const char *server_ip;
549 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
550 sconn->remote_port));
552 /* Connect to remote host */
553 server_ip = server->config->server_info->primary == NULL ? NULL :
554 server->config->server_info->primary->server_ip;
555 sock = silc_net_create_connection(server_ip, sconn->remote_port,
558 silc_schedule_task_add(server->schedule, 0,
559 silc_server_backup_connect_to_router,
560 context, 5, 0, SILC_TASK_TIMEOUT,
561 SILC_TASK_PRI_NORMAL);
565 /* Continue with key exchange protocol */
566 silc_server_start_key_exchange(server, sconn, sock);
569 /* Constantly tries to reconnect to a primary router indicated by the
570 `ip' and `port'. The `connected' callback will be called when the
571 connection is created. */
573 void silc_server_backup_reconnect(SilcServer server,
574 const char *ip, SilcUInt16 port,
575 SilcServerConnectRouterCallback callback,
578 SilcServerConnection sconn;
580 sconn = silc_calloc(1, sizeof(*sconn));
581 sconn->server = server;
582 sconn->remote_host = strdup(ip);
583 sconn->remote_port = port;
584 sconn->callback = callback;
585 sconn->callback_context = context;
586 sconn->no_reconnect = TRUE;
587 silc_schedule_task_add(server->schedule, 0,
588 silc_server_backup_connect_to_router,
589 sconn, 1, 0, SILC_TASK_TIMEOUT,
590 SILC_TASK_PRI_NORMAL);
593 /* Task that is called after backup router has connected back to
594 primary router and we are starting the resuming protocol */
596 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
598 SilcServerBackupProtocolContext proto_ctx =
599 (SilcServerBackupProtocolContext)context;
600 SilcServer server = proto_ctx->server;
601 SilcSocketConnection sock = proto_ctx->sock;
603 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
605 /* Run the backup resuming protocol */
606 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
607 &sock->protocol, proto_ctx,
608 silc_server_protocol_backup_done);
609 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
612 /* Called when we've established connection back to our primary router
613 when we've acting as backup router and have replaced the primary router
614 in the cell. This function will start the backup resuming protocol. */
616 void silc_server_backup_connected(SilcServer server,
617 SilcServerEntry server_entry,
620 SilcServerBackupProtocolContext proto_ctx;
621 SilcSocketConnection sock;
625 SilcServerConfigRouter *primary;
626 primary = silc_server_config_get_primary_router(server);
628 silc_server_backup_reconnect(server,
629 primary->host, primary->port,
630 silc_server_backup_connected,
635 sock = (SilcSocketConnection)server_entry->connection;
636 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
637 proto_ctx->server = server;
638 proto_ctx->sock = sock;
639 proto_ctx->responder = FALSE;
640 proto_ctx->type = SILC_SERVER_BACKUP_START;
641 proto_ctx->start = time(0);
643 /* Start through scheduler */
644 silc_schedule_task_add(server->schedule, 0,
645 silc_server_backup_connected_later,
648 SILC_TASK_PRI_NORMAL);
651 /* Called when normal server has connected to its primary router after
652 backup router has sent the START packet in reusming protocol. We will
653 move the protocol context from the backup router connection to the
656 static void silc_server_backup_connect_primary(SilcServer server,
657 SilcServerEntry server_entry,
660 SilcSocketConnection backup_router = (SilcSocketConnection)context;
661 SilcServerBackupProtocolContext ctx;
662 SilcSocketConnection sock;
663 SilcIDListData idata;
668 SilcServerConfigRouter *primary;
669 primary = silc_server_config_get_primary_router(server);
671 silc_server_backup_reconnect(server,
672 primary->host, primary->port,
673 silc_server_backup_connect_primary,
678 ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context;
679 sock = (SilcSocketConnection)server_entry->connection;
680 idata = (SilcIDListData)server_entry;
682 SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
684 /* Send the CONNECTED packet back to the backup router. */
685 buffer = silc_buffer_alloc(2);
686 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
687 silc_buffer_format(buffer,
688 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
689 SILC_STR_UI_CHAR(ctx->session),
691 silc_server_packet_send(server, backup_router,
692 SILC_PACKET_RESUME_ROUTER, 0,
693 buffer->data, buffer->len, FALSE);
694 silc_buffer_free(buffer);
696 /* The primary connection is disabled until it sends the RESUMED packet
698 idata->status |= SILC_IDLIST_STATUS_DISABLED;
700 /* Move this protocol context from this backup router connection to
701 the primary router connection since it will send the subsequent
702 packets in this protocol. We don't talk with backup router
704 sock->protocol = backup_router->protocol;
705 ctx->sock = (SilcSocketConnection)server_entry->connection;
706 backup_router->protocol = NULL;
709 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
711 SilcProtocol protocol = (SilcProtocol)context;
712 SilcServerBackupProtocolContext ctx = protocol->context;
713 SilcServer server = ctx->server;
717 for (i = 0; i < ctx->sessions_count; i++)
718 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
719 ctx->session = ctx->sessions[i].session;
721 /* We've received all the CONNECTED packets and now we'll send the
722 ENDING packet to the new primary router. */
723 packet = silc_buffer_alloc(2);
724 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
725 silc_buffer_format(packet,
726 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
727 SILC_STR_UI_CHAR(ctx->session),
729 silc_server_packet_send(server, ctx->sock,
730 SILC_PACKET_RESUME_ROUTER, 0,
731 packet->data, packet->len, FALSE);
732 silc_buffer_free(packet);
734 protocol->state = SILC_PROTOCOL_STATE_END;
737 /* Backup resuming protocol. This protocol is executed when the primary
738 router wants to resume its position as being primary router. */
740 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
742 SilcProtocol protocol = (SilcProtocol)context;
743 SilcServerBackupProtocolContext ctx = protocol->context;
744 SilcServer server = ctx->server;
746 SilcIDCacheList list;
747 SilcIDCacheEntry id_cache;
748 SilcServerEntry server_entry;
751 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
752 protocol->state = SILC_PROTOCOL_STATE_START;
754 switch(protocol->state) {
755 case SILC_PROTOCOL_STATE_START:
756 if (ctx->responder == FALSE) {
757 /* Initiator of the protocol. We are backup router */
759 packet = silc_buffer_alloc(2);
760 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
762 /* Send the START packet to primary router and normal servers. */
763 if (silc_idcache_get_all(server->local_list->servers, &list)) {
764 if (silc_idcache_list_first(list, &id_cache)) {
766 server_entry = (SilcServerEntry)id_cache->context;
767 if (!server_entry || (server_entry == server->id_entry) ||
768 !server_entry->connection || !server_entry->data.send_key ||
769 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
770 if (!silc_idcache_list_next(list, &id_cache))
776 ctx->sessions = silc_realloc(ctx->sessions,
777 sizeof(*ctx->sessions) *
778 (ctx->sessions_count + 1));
779 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
780 ctx->sessions[ctx->sessions_count].connected = FALSE;
781 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
783 SILC_LOG_DEBUG(("Sending START to %s (session %d)",
784 server_entry->server_name, ctx->sessions_count));
786 /* This connection is performing this protocol too now */
787 ((SilcSocketConnection)server_entry->connection)->protocol =
790 if (server_entry->server_type == SILC_ROUTER)
791 packet->data[0] = SILC_SERVER_BACKUP_START;
793 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
794 packet->data[1] = ctx->sessions_count;
795 silc_server_packet_send(server, server_entry->connection,
796 SILC_PACKET_RESUME_ROUTER, 0,
797 packet->data, packet->len, FALSE);
798 ctx->sessions_count++;
800 if (!silc_idcache_list_next(list, &id_cache))
805 silc_idcache_list_free(list);
808 if (silc_idcache_get_all(server->global_list->servers, &list)) {
809 if (silc_idcache_list_first(list, &id_cache)) {
811 server_entry = (SilcServerEntry)id_cache->context;
812 if (!server_entry || (server_entry == server->id_entry) ||
813 !server_entry->connection || !server_entry->data.send_key ||
814 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
815 if (!silc_idcache_list_next(list, &id_cache))
821 ctx->sessions = silc_realloc(ctx->sessions,
822 sizeof(*ctx->sessions) *
823 (ctx->sessions_count + 1));
824 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
825 ctx->sessions[ctx->sessions_count].connected = FALSE;
826 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
828 SILC_LOG_DEBUG(("Sending START to %s (session %d)",
829 server_entry->server_name, ctx->sessions_count));
831 /* This connection is performing this protocol too now */
832 ((SilcSocketConnection)server_entry->connection)->protocol =
835 if (server_entry->server_type == SILC_ROUTER)
836 packet->data[0] = SILC_SERVER_BACKUP_START;
838 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
839 packet->data[1] = ctx->sessions_count;
840 silc_server_packet_send(server, server_entry->connection,
841 SILC_PACKET_RESUME_ROUTER, 0,
842 packet->data, packet->len, FALSE);
843 ctx->sessions_count++;
845 if (!silc_idcache_list_next(list, &id_cache))
850 silc_idcache_list_free(list);
853 silc_buffer_free(packet);
855 /* If we are not standalone and our primary is not the one we've
856 talking to now, then announce our information to it since we
857 haven't done that yet. Standalone backup router announces
858 these during connecting to the primary. */
859 if (!server->standalone && SILC_PRIMARY_ROUTE(server) != ctx->sock) {
860 silc_server_announce_servers(server, TRUE, 0, ctx->sock);
861 silc_server_announce_clients(server, 0, ctx->sock);
862 silc_server_announce_channels(server, 0, ctx->sock);
867 /* Responder of the protocol. */
868 SilcServerConfigRouter *primary;
870 /* We should have received START or START_GLOBAL packet */
871 if (ctx->type != SILC_SERVER_BACKUP_START &&
872 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
873 SILC_LOG_DEBUG(("Bad resume router packet"));
877 /* Connect to the primary router that was down that is now supposed
878 to be back online. We send the CONNECTED packet after we've
879 established the connection to the primary router. */
880 primary = silc_server_config_get_primary_router(server);
881 if (primary && server->backup_primary) {
882 SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
884 silc_server_backup_reconnect(server,
885 primary->host, primary->port,
886 silc_server_backup_connect_primary,
889 /* Nowhere to connect just return the CONNECTED packet */
890 SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
893 /* Send the CONNECTED packet back to the backup router. */
894 packet = silc_buffer_alloc(2);
895 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
896 silc_buffer_format(packet,
897 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
898 SILC_STR_UI_CHAR(ctx->session),
900 silc_server_packet_send(server, ctx->sock,
901 SILC_PACKET_RESUME_ROUTER, 0,
902 packet->data, packet->len, FALSE);
903 silc_buffer_free(packet);
906 if (server->server_type == SILC_ROUTER &&
908 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
911 protocol->state = SILC_PROTOCOL_STATE_END;
913 ctx->sessions = silc_realloc(ctx->sessions,
914 sizeof(*ctx->sessions) *
915 (ctx->sessions_count + 1));
916 ctx->sessions[ctx->sessions_count].session = ctx->session;
917 ctx->sessions_count++;
922 if (ctx->responder == FALSE) {
925 /* We should have received CONNECTED packet */
926 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
927 SILC_LOG_DEBUG(("Bad resume router packet"));
931 SILC_LOG_DEBUG(("Received CONNECTED (session %d)", ctx->session));
933 for (i = 0; i < ctx->sessions_count; i++) {
934 if (ctx->sessions[i].session == ctx->session) {
935 ctx->sessions[i].connected = TRUE;
940 for (i = 0; i < ctx->sessions_count; i++) {
941 if (!ctx->sessions[i].connected)
945 SILC_LOG_DEBUG(("All sessions has returned CONNECTED packets"));
946 SILC_LOG_DEBUG(("Sending ENDING packet to primary router"));
948 /* Send with a timeout */
949 silc_schedule_task_add(server->schedule, 0,
950 silc_server_backup_send_resumed,
951 protocol, 1, 0, SILC_TASK_TIMEOUT,
952 SILC_TASK_PRI_NORMAL);
957 /* We should have been received ENDING packet */
958 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
959 SILC_LOG_DEBUG(("Bad resume router packet"));
963 SILC_LOG_DEBUG(("Received ENDING packet, we are going to resume now"));
965 /* This state is received by the primary router but also servers
966 and perhaps other routers so check that if we are the primary
967 router of the cell then start sending RESUMED packets. If we
968 are normal server or one of those other routers then procede
970 if (server->router &&
971 !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
972 silc_server_config_is_primary_route(server)) {
973 /* We'll wait for RESUMED packet */
974 protocol->state = SILC_PROTOCOL_STATE_END;
978 /* Switch announced informations to our primary router of using the
980 silc_server_local_servers_toggle_enabled(server, TRUE);
981 silc_server_update_servers_by_server(server, ctx->sock->user_data,
983 silc_server_update_clients_by_server(server, ctx->sock->user_data,
984 server->router, TRUE);
985 if (server->server_type == SILC_SERVER)
986 silc_server_update_channels_by_server(server, ctx->sock->user_data,
989 packet = silc_buffer_alloc(2);
990 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
992 /* We are the primary router, start sending RESUMED packets. */
993 if (silc_idcache_get_all(server->local_list->servers, &list)) {
994 if (silc_idcache_list_first(list, &id_cache)) {
996 server_entry = (SilcServerEntry)id_cache->context;
997 if (!server_entry || (server_entry == server->id_entry) ||
998 !server_entry->connection || !server_entry->data.send_key) {
999 if (!silc_idcache_list_next(list, &id_cache))
1005 SILC_LOG_DEBUG(("Sending RESUMED to %s",
1006 server_entry->server_name));
1008 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1010 /* This connection is performing this protocol too now */
1011 ((SilcSocketConnection)server_entry->connection)->protocol =
1014 if (server_entry->server_type == SILC_ROUTER)
1015 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1017 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1018 silc_server_packet_send(server, server_entry->connection,
1019 SILC_PACKET_RESUME_ROUTER, 0,
1020 packet->data, packet->len, FALSE);
1022 if (!silc_idcache_list_next(list, &id_cache))
1027 silc_idcache_list_free(list);
1030 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1031 if (silc_idcache_list_first(list, &id_cache)) {
1033 server_entry = (SilcServerEntry)id_cache->context;
1034 if (!server_entry || (server_entry == server->id_entry) ||
1035 !server_entry->connection || !server_entry->data.send_key) {
1036 if (!silc_idcache_list_next(list, &id_cache))
1042 SILC_LOG_DEBUG(("Sending RESUMED to %s",
1043 server_entry->server_name));
1045 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1047 /* This connection is performing this protocol too now */
1048 ((SilcSocketConnection)server_entry->connection)->protocol =
1051 if (server_entry->server_type == SILC_ROUTER)
1052 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1054 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1055 silc_server_packet_send(server, server_entry->connection,
1056 SILC_PACKET_RESUME_ROUTER, 0,
1057 packet->data, packet->len, FALSE);
1059 if (!silc_idcache_list_next(list, &id_cache))
1064 silc_idcache_list_free(list);
1067 silc_buffer_free(packet);
1069 SILC_LOG_INFO(("We are now the primary router of our cell again"));
1070 server->wait_backup = FALSE;
1072 /* For us this is the end of this protocol. */
1073 if (protocol->final_callback)
1074 silc_protocol_execute_final(protocol, server->schedule);
1076 silc_protocol_free(protocol);
1080 case SILC_PROTOCOL_STATE_END:
1082 SilcServerEntry router, backup_router;
1084 /* We should have been received RESUMED packet from our primary
1086 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1087 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1088 SILC_LOG_DEBUG(("Bad resume router packet"));
1092 SILC_LOG_DEBUG(("Received RESUMED from new primary router"));
1094 if (server->backup_router)
1095 server->server_type = SILC_BACKUP_ROUTER;
1097 /* We have now new primary router. All traffic goes there from now on. */
1098 router = (SilcServerEntry)ctx->sock->user_data;
1099 if (silc_server_backup_replaced_get(server, router->id,
1102 if (backup_router == server->router) {
1103 /* We have new primary router now */
1104 server->id_entry->router = router;
1105 server->router = router;
1106 SILC_LOG_INFO(("Switching back to primary router %s",
1107 server->router->server_name));
1109 /* We are connected to new primary and now continue using it */
1110 SILC_LOG_INFO(("Resuming the use of primary router %s",
1111 router->server_name));
1114 /* Update the client entries of the backup router to the new
1116 silc_server_local_servers_toggle_enabled(server, FALSE);
1117 router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1118 silc_server_update_servers_by_server(server, backup_router, router);
1119 silc_server_update_clients_by_server(server, NULL, router, FALSE);
1120 if (server->server_type == SILC_SERVER)
1121 silc_server_update_channels_by_server(server, backup_router, router);
1122 silc_server_backup_replaced_del(server, backup_router);
1124 /* Announce all of our information to the router. */
1125 if (server->server_type == SILC_ROUTER)
1126 silc_server_announce_servers(server, FALSE, ctx->start,
1127 router->connection);
1129 /* Announce our clients and channels to the router */
1130 silc_server_announce_clients(server, ctx->start,
1131 router->connection);
1132 silc_server_announce_channels(server, ctx->start,
1133 router->connection);
1136 /* Send notify about primary router going down to local operators */
1137 SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1138 SILC_NOTIFY_TYPE_NONE,
1139 ("%s resumed the use of primary router %s",
1140 server->server_name,
1141 server->router->server_name));
1143 /* Protocol has ended, call the final callback */
1144 if (protocol->final_callback)
1145 silc_protocol_execute_final(protocol, server->schedule);
1147 silc_protocol_free(protocol);
1151 case SILC_PROTOCOL_STATE_ERROR:
1152 /* Protocol has ended, call the final callback */
1153 if (protocol->final_callback)
1154 silc_protocol_execute_final(protocol, server->schedule);
1156 silc_protocol_free(protocol);
1159 case SILC_PROTOCOL_STATE_FAILURE:
1160 /* Protocol has ended, call the final callback */
1161 if (protocol->final_callback)
1162 silc_protocol_execute_final(protocol, server->schedule);
1164 silc_protocol_free(protocol);
1167 case SILC_PROTOCOL_STATE_UNKNOWN:
1172 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1174 SilcProtocol protocol = (SilcProtocol)context;
1175 SilcServerBackupProtocolContext ctx = protocol->context;
1176 SilcServer server = ctx->server;
1177 SilcServerEntry server_entry;
1178 SilcSocketConnection sock;
1179 SilcIDCacheList list;
1180 SilcIDCacheEntry id_cache;
1182 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1183 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1184 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1187 /* Remove this protocol from all server entries that has it */
1188 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1189 if (silc_idcache_list_first(list, &id_cache)) {
1191 server_entry = (SilcServerEntry)id_cache->context;
1192 sock = (SilcSocketConnection)server_entry->connection;
1194 if (sock->protocol == protocol) {
1195 sock->protocol = NULL;
1197 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1198 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1201 if (!silc_idcache_list_next(list, &id_cache))
1205 silc_idcache_list_free(list);
1208 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1209 if (silc_idcache_list_first(list, &id_cache)) {
1211 server_entry = (SilcServerEntry)id_cache->context;
1212 sock = (SilcSocketConnection)server_entry->connection;
1214 if (sock->protocol == protocol) {
1215 sock->protocol = NULL;
1217 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1218 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1221 if (!silc_idcache_list_next(list, &id_cache))
1225 silc_idcache_list_free(list);
1228 SILC_LOG_DEBUG(("Backup resuming protocol has ended"));
1230 if (ctx->sock->protocol)
1231 ctx->sock->protocol = NULL;
1232 silc_protocol_free(protocol);
1233 silc_free(ctx->sessions);