5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
28 SilcServerEntry server;
32 } SilcServerBackupEntry;
34 /* Holds IP address and port of the primary router that was replaced
39 SilcServerEntry server; /* Backup router that replaced the primary */
40 } SilcServerBackupReplaced;
43 struct SilcServerBackupStruct {
44 SilcServerBackupEntry *servers;
45 SilcUInt32 servers_count;
46 SilcServerBackupReplaced **replaced;
47 SilcUInt32 replaced_count;
53 SilcServerEntry server_entry;
54 } SilcServerBackupProtocolSession;
56 /* Backup resuming protocol context */
59 SilcSocketConnection sock;
63 SilcServerBackupProtocolSession *sessions;
64 SilcUInt32 sessions_count;
66 } *SilcServerBackupProtocolContext;
68 /* Adds the `backup_server' to be one of our backup router. This can be
69 called multiple times to set multiple backup routers. The `ip' and `port'
70 is the IP and port that the `backup_router' will replace if the `ip'
71 will become unresponsive. If `local' is TRUE then the `backup_server' is
72 in the local cell, if FALSE it is in some other cell. */
74 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
75 const char *ip, int port, bool local)
79 SILC_LOG_DEBUG(("Start"));
85 server->backup = silc_calloc(1, sizeof(*server->backup));
87 for (i = 0; i < server->backup->servers_count; i++) {
88 if (!server->backup->servers[i].server) {
89 server->backup->servers[i].server = backup_server;
90 server->backup->servers[i].local = local;
91 memset(server->backup->servers[i].ip.data, 0,
92 sizeof(server->backup->servers[i].ip.data));
93 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
94 sizeof(server->backup->servers[i].ip.data));
95 //server->backup->servers[i].port = port;
100 i = server->backup->servers_count;
101 server->backup->servers = silc_realloc(server->backup->servers,
102 sizeof(*server->backup->servers) *
104 server->backup->servers[i].server = backup_server;
105 server->backup->servers[i].local = local;
106 memset(server->backup->servers[i].ip.data, 0,
107 sizeof(server->backup->servers[i].ip.data));
108 silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
109 sizeof(server->backup->servers[i].ip.data));
110 //server->backup->servers[i].port = server_id->port;
111 server->backup->servers_count++;
114 /* Returns backup router for IP and port in `replacing' or NULL if there
115 does not exist backup router. */
117 SilcServerEntry silc_server_backup_get(SilcServer server,
118 SilcServerID *server_id)
122 SILC_LOG_DEBUG(("Start"));
127 for (i = 0; i < server->backup->servers_count; i++) {
128 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 const SilcBufferStruct p;
274 SilcIDListData idata;
277 if (!server->backup || server->server_type != SILC_ROUTER)
280 SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
282 buffer = packet->buffer;
283 silc_buffer_push(buffer, buffer->data - buffer->head);
285 for (i = 0; i < server->backup->servers_count; i++) {
286 backup = server->backup->servers[i].server;
288 if (!backup || backup->connection == sender ||
289 server->backup->servers[i].local == FALSE)
292 idata = (SilcIDListData)backup;
293 sock = backup->connection;
295 if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
296 (const SilcBuffer)&p)) {
297 SILC_LOG_ERROR(("Cannot send packet"));
300 silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
301 silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
302 (SilcBuffer)&p, p.len);
304 SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len);
306 /* Now actually send the packet */
307 silc_server_packet_send_real(server, sock, FALSE);
311 /* A generic routine to send data to all backup routers. If the `sender'
312 is provided it will indicate the original sender of the packet and the
313 packet won't be resent to that entity. The `data' is the data that will
314 be assembled to packet context before sending. The packet will be
315 encrypted this function. If the `force_send' is TRUE the data is sent
316 immediately and not put to queue. If `local' is TRUE then the packet
317 will be sent only to local backup routers inside the cell. If false the
318 packet can go from one cell to the other. This function has no effect
319 if there are no any backup routers. */
321 void silc_server_backup_send(SilcServer server,
322 SilcServerEntry sender,
324 SilcPacketFlags flags,
330 SilcServerEntry backup;
331 SilcSocketConnection sock;
334 if (!server->backup || server->server_type != SILC_ROUTER)
337 SILC_LOG_DEBUG(("Start"));
339 for (i = 0; i < server->backup->servers_count; i++) {
340 backup = server->backup->servers[i].server;
344 if (sender == backup)
347 if (local && server->backup->servers[i].local == FALSE)
350 sock = backup->connection;
351 silc_server_packet_send(server, backup->connection, type, flags,
352 data, data_len, force_send);
356 /* Same as silc_server_backup_send but sets a specific Destination ID to
357 the packet. The Destination ID is indicated by the `dst_id' and the
358 ID type `dst_id_type'. For example, packets destined to channels must
359 be sent using this function. */
361 void silc_server_backup_send_dest(SilcServer server,
362 SilcServerEntry sender,
364 SilcPacketFlags flags,
366 SilcIdType dst_id_type,
372 SilcServerEntry backup;
373 SilcSocketConnection sock;
376 if (!server->backup || server->server_type != SILC_ROUTER)
379 SILC_LOG_DEBUG(("Start"));
381 for (i = 0; i < server->backup->servers_count; i++) {
382 backup = server->backup->servers[i].server;
386 if (sender == backup)
389 if (local && server->backup->servers[i].local == FALSE)
392 sock = backup->connection;
393 silc_server_packet_send_dest(server, backup->connection, type, flags,
394 dst_id, dst_id_type, data, data_len,
399 /* Processes incoming RESUME_ROUTER packet. This can give the packet
400 for processing to the protocol handler or allocate new protocol if
401 start command is received. */
403 void silc_server_backup_resume_router(SilcServer server,
404 SilcSocketConnection sock,
405 SilcPacketContext *packet)
407 SilcUInt8 type, session;
408 SilcServerBackupProtocolContext ctx;
411 if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
412 sock->type == SILC_SOCKET_TYPE_UNKNOWN)
415 SILC_LOG_DEBUG(("Start"));
417 ret = silc_buffer_unformat(packet->buffer,
418 SILC_STR_UI_CHAR(&type),
419 SILC_STR_UI_CHAR(&session),
424 /* Activate the protocol for this socket if necessary */
425 if ((type == SILC_SERVER_BACKUP_RESUMED ||
426 type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
427 sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol &&
428 ((SilcIDListData)sock->user_data)->status &
429 SILC_IDLIST_STATUS_DISABLED) {
430 SilcServerEntry backup_router;
432 if (silc_server_backup_replaced_get(server,
433 ((SilcServerEntry)sock->
436 SilcSocketConnection bsock =
437 (SilcSocketConnection)backup_router->connection;
438 if (bsock->protocol && bsock->protocol->protocol &&
439 bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
440 sock->protocol = bsock->protocol;
441 ctx = sock->protocol->context;
447 /* If the backup resuming protocol is active then process the packet
449 if (sock->protocol && sock->protocol->protocol &&
450 sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
451 ctx = sock->protocol->context;
454 SILC_LOG_DEBUG(("********************************"));
455 SILC_LOG_DEBUG(("Continuing protocol, type %d", type));
457 if (type != SILC_SERVER_BACKUP_RESUMED &&
458 type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
459 for (i = 0; i < ctx->sessions_count; i++) {
460 if (session == ctx->sessions[i].session) {
461 ctx->session = session;
462 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
467 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
471 SILC_LOG_DEBUG(("Bad resume router packet"));
475 /* We don't have protocol active. If we are router and the packet is
476 coming from our primary router then lets check whether it means we've
477 been replaced by an backup router in my cell. This is usually received
478 immediately after we've connected to our primary router. */
480 if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
481 server->router == sock->user_data &&
482 type == SILC_SERVER_BACKUP_REPLACED) {
483 /* We have been replaced by an backup router in our cell. We must
484 mark our primary router connection disabled since we are not allowed
485 to use it at this moment. */
486 SilcIDListData idata = (SilcIDListData)sock->user_data;
488 SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
489 "wait until backup resuming protocol is executed"));
491 SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
492 idata->status |= SILC_IDLIST_STATUS_DISABLED;
496 if (type == SILC_SERVER_BACKUP_START ||
497 type == SILC_SERVER_BACKUP_START_GLOBAL) {
498 /* We have received a start for resuming protocol. */
499 SilcServerBackupProtocolContext proto_ctx;
501 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
502 proto_ctx->server = server;
503 proto_ctx->sock = sock;
504 proto_ctx->responder = TRUE;
505 proto_ctx->type = type;
506 proto_ctx->session = session;
507 proto_ctx->start = time(0);
509 SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
511 /* Run the backup resuming protocol */
512 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
513 &sock->protocol, proto_ctx,
514 silc_server_protocol_backup_done);
515 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
519 /* Timeout task callback to connect to remote router */
521 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
523 SilcServerConnection sconn = (SilcServerConnection)context;
524 SilcServer server = sconn->server;
526 const char *server_ip;
528 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
529 sconn->remote_port));
531 /* Connect to remote host */
532 server_ip = server->config->server_info->primary == NULL ? NULL :
533 server->config->server_info->primary->server_ip;
534 sock = silc_net_create_connection(server_ip, sconn->remote_port,
537 silc_schedule_task_add(server->schedule, 0,
538 silc_server_backup_connect_to_router,
539 context, 5, 0, SILC_TASK_TIMEOUT,
540 SILC_TASK_PRI_NORMAL);
544 /* Continue with key exchange protocol */
545 silc_server_start_key_exchange(server, sconn, sock);
548 /* Constantly tries to reconnect to a primary router indicated by the
549 `ip' and `port'. The `connected' callback will be called when the
550 connection is created. */
552 void silc_server_backup_reconnect(SilcServer server,
553 const char *ip, SilcUInt16 port,
554 SilcServerConnectRouterCallback callback,
557 SilcServerConnection sconn;
559 sconn = silc_calloc(1, sizeof(*sconn));
560 sconn->server = server;
561 sconn->remote_host = strdup(ip);
562 sconn->remote_port = port;
563 sconn->callback = callback;
564 sconn->callback_context = context;
565 silc_schedule_task_add(server->schedule, 0,
566 silc_server_backup_connect_to_router,
567 sconn, 1, 0, SILC_TASK_TIMEOUT,
568 SILC_TASK_PRI_NORMAL);
571 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
573 SilcServerBackupProtocolContext proto_ctx =
574 (SilcServerBackupProtocolContext)context;
575 SilcServer server = proto_ctx->server;
576 SilcSocketConnection sock = proto_ctx->sock;
578 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
580 /* Run the backup resuming protocol */
581 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
582 &sock->protocol, proto_ctx,
583 silc_server_protocol_backup_done);
584 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
587 /* Called when we've established connection back to our primary router
588 when we've acting as backup router and have replaced the primary router
589 in the cell. This function will start the backup resuming protocol. */
591 void silc_server_backup_connected(SilcServer server,
592 SilcServerEntry server_entry,
595 SilcServerBackupProtocolContext proto_ctx;
596 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
598 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
599 proto_ctx->server = server;
600 proto_ctx->sock = sock;
601 proto_ctx->responder = FALSE;
602 proto_ctx->type = SILC_SERVER_BACKUP_START;
603 proto_ctx->start = time(0);
605 /* Start through scheduler */
606 silc_schedule_task_add(server->schedule, 0,
607 silc_server_backup_connected_later,
610 SILC_TASK_PRI_NORMAL);
613 /* Called when normal server has connected to its primary router after
614 backup router has sent the START packet in reusming protocol. We will
615 move the protocol context from the backup router connection to the
618 static void silc_server_backup_connect_primary(SilcServer server,
619 SilcServerEntry server_entry,
622 SilcSocketConnection backup_router = (SilcSocketConnection)context;
623 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
624 SilcIDListData idata = (SilcIDListData)server_entry;
625 SilcServerBackupProtocolContext ctx =
626 (SilcServerBackupProtocolContext)backup_router->protocol->context;
629 SILC_LOG_DEBUG(("Start"));
631 SILC_LOG_DEBUG(("********************************"));
632 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
634 /* Send the CONNECTED packet back to the backup router. */
635 buffer = silc_buffer_alloc(2);
636 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
637 silc_buffer_format(buffer,
638 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
639 SILC_STR_UI_CHAR(ctx->session),
641 silc_server_packet_send(server, backup_router,
642 SILC_PACKET_RESUME_ROUTER, 0,
643 buffer->data, buffer->len, FALSE);
644 silc_buffer_free(buffer);
646 /* The primary connection is disabled until it sends the RESUMED packet
648 idata->status |= SILC_IDLIST_STATUS_DISABLED;
650 /* Move this protocol context from this backup router connection to
651 the primary router connection since it will send the subsequent
652 packets in this protocol. We don't talk with backup router
654 sock->protocol = backup_router->protocol;
655 ctx->sock = (SilcSocketConnection)server_entry->connection;
656 backup_router->protocol = NULL;
659 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
661 SilcProtocol protocol = (SilcProtocol)context;
662 SilcServerBackupProtocolContext ctx = protocol->context;
663 SilcServer server = ctx->server;
667 for (i = 0; i < ctx->sessions_count; i++)
668 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
669 ctx->session = ctx->sessions[i].session;
671 /* We've received all the CONNECTED packets and now we'll send the
672 ENDING packet to the new primary router. */
673 packet = silc_buffer_alloc(2);
674 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
675 silc_buffer_format(packet,
676 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
677 SILC_STR_UI_CHAR(ctx->session),
679 silc_server_packet_send(server, ctx->sock,
680 SILC_PACKET_RESUME_ROUTER, 0,
681 packet->data, packet->len, FALSE);
682 silc_buffer_free(packet);
684 protocol->state = SILC_PROTOCOL_STATE_END;
687 /* Resume protocol with RESUME_ROUTER packet:
689 SILC_PACKET_RESUME_ROUTER:
691 <SilcUInt8 type> <SilcUInt8 Session ID>
693 <type> = the protocol opcode
694 <Session ID> = Identifier for this packet and any subsequent reply
695 packets must include this identifier.
699 1 = To router: Comensing backup resuming protocol. This will
700 indicate that the sender is backup router acting as primary
701 and the receiver is primary router that has been replaced by
704 To server. Comensing backup resuming protocol. This will
705 indicate that the sender is backup router and the receiver
706 must reconnect to the real primary router of the cell.
708 2 = To Router: Comesning backup resuming protocol in another
709 cell. The receiver will connect to its primary router
710 (the router that is now online again) but will not use
711 the link. If the receiver is not configured to connect
712 to any router it does as locally configured. The sender
713 is always backup router.
715 To server: this is never sent to server.
717 3 = To backup router: Sender is normal server or router and it
718 tells to backup router that they have connected to the
719 primary router. Backup router never sends this type.
721 4 = To router: Ending backup resuming protocol. This is sent
722 to the real primary router to tell that it can take over
723 the task as being primary router.
725 To server: same as sending for router.
727 Backup router sends this also to the primary route but only
728 after it has sent them to normal servers and has purged all
729 traffic coming from normal servers.
731 5 = To router: Sender is the real primary router after it has
732 received type 4 from backup router. To tell that it is again
733 primary router of the cell.
735 20 = To router: This is sent only when router is connecting to
736 another router and has been replaced by an backup router.
737 The sender knows that the connectee has been replaced.
741 /* Backup resuming protocol. This protocol is executed when the primary
742 router wants to resume its position as being primary router. */
744 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
746 SilcProtocol protocol = (SilcProtocol)context;
747 SilcServerBackupProtocolContext ctx = protocol->context;
748 SilcServer server = ctx->server;
750 SilcIDCacheList list;
751 SilcIDCacheEntry id_cache;
752 SilcServerEntry server_entry;
755 SILC_LOG_DEBUG(("Start"));
757 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
758 protocol->state = SILC_PROTOCOL_STATE_START;
760 SILC_LOG_DEBUG(("State=%d", protocol->state));
762 switch(protocol->state) {
763 case SILC_PROTOCOL_STATE_START:
764 if (ctx->responder == FALSE) {
765 /* Initiator of the protocol. We are backup router */
767 packet = silc_buffer_alloc(2);
768 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
770 SILC_LOG_DEBUG(("********************************"));
771 SILC_LOG_DEBUG(("Sending START packets"));
773 /* Send the START packet to primary router and normal servers. */
774 if (silc_idcache_get_all(server->local_list->servers, &list)) {
775 if (silc_idcache_list_first(list, &id_cache)) {
777 server_entry = (SilcServerEntry)id_cache->context;
778 if (!server_entry || (server_entry == server->id_entry) ||
779 !server_entry->connection || !server_entry->data.send_key ||
780 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
781 if (!silc_idcache_list_next(list, &id_cache))
787 ctx->sessions = silc_realloc(ctx->sessions,
788 sizeof(*ctx->sessions) *
789 (ctx->sessions_count + 1));
790 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
791 ctx->sessions[ctx->sessions_count].connected = FALSE;
792 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
794 SILC_LOG_DEBUG(("********************************"));
795 SILC_LOG_DEBUG(("START (local) for session %d",
796 ctx->sessions_count));
798 /* This connection is performing this protocol too now */
799 ((SilcSocketConnection)server_entry->connection)->protocol =
802 if (server_entry->server_type == SILC_ROUTER)
803 packet->data[0] = SILC_SERVER_BACKUP_START;
805 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
806 packet->data[1] = ctx->sessions_count;
807 silc_server_packet_send(server, server_entry->connection,
808 SILC_PACKET_RESUME_ROUTER, 0,
809 packet->data, packet->len, FALSE);
810 ctx->sessions_count++;
812 if (!silc_idcache_list_next(list, &id_cache))
817 silc_idcache_list_free(list);
820 if (silc_idcache_get_all(server->global_list->servers, &list)) {
821 if (silc_idcache_list_first(list, &id_cache)) {
823 server_entry = (SilcServerEntry)id_cache->context;
824 if (!server_entry || (server_entry == server->id_entry) ||
825 !server_entry->connection || !server_entry->data.send_key ||
826 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
827 if (!silc_idcache_list_next(list, &id_cache))
833 ctx->sessions = silc_realloc(ctx->sessions,
834 sizeof(*ctx->sessions) *
835 (ctx->sessions_count + 1));
836 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
837 ctx->sessions[ctx->sessions_count].connected = FALSE;
838 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
840 SILC_LOG_DEBUG(("********************************"));
841 SILC_LOG_DEBUG(("START (global) for session %d",
842 ctx->sessions_count));
844 /* This connection is performing this protocol too now */
845 ((SilcSocketConnection)server_entry->connection)->protocol =
848 if (server_entry->server_type == SILC_ROUTER)
849 packet->data[0] = SILC_SERVER_BACKUP_START;
851 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
852 packet->data[1] = ctx->sessions_count;
853 silc_server_packet_send(server, server_entry->connection,
854 SILC_PACKET_RESUME_ROUTER, 0,
855 packet->data, packet->len, FALSE);
856 ctx->sessions_count++;
858 if (!silc_idcache_list_next(list, &id_cache))
863 silc_idcache_list_free(list);
866 silc_buffer_free(packet);
868 /* Announce all of our information */
869 silc_server_announce_servers(server, TRUE, 0, ctx->sock);
870 silc_server_announce_clients(server, 0, ctx->sock);
871 silc_server_announce_channels(server, 0, ctx->sock);
875 /* Responder of the protocol. */
876 SilcServerConfigRouter *primary;
878 /* We should have received START or START_GLOBAL packet */
879 if (ctx->type != SILC_SERVER_BACKUP_START &&
880 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
881 SILC_LOG_DEBUG(("Bad resume router packet"));
885 SILC_LOG_DEBUG(("********************************"));
886 SILC_LOG_DEBUG(("Received START packet, reconnecting to router"));
888 /* Connect to the primary router that was down that is now supposed
889 to be back online. We send the CONNECTED packet after we've
890 established the connection to the primary router. */
891 primary = silc_server_config_get_primary_router(server);
892 if (primary && server->backup_primary) {
893 silc_server_backup_reconnect(server,
894 primary->host, primary->port,
895 silc_server_backup_connect_primary,
898 /* Nowhere to connect just return the CONNECTED packet */
900 SILC_LOG_DEBUG(("********************************"));
901 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
903 /* Send the CONNECTED packet back to the backup router. */
904 packet = silc_buffer_alloc(2);
905 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
906 silc_buffer_format(packet,
907 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
908 SILC_STR_UI_CHAR(ctx->session),
910 silc_server_packet_send(server, ctx->sock,
911 SILC_PACKET_RESUME_ROUTER, 0,
912 packet->data, packet->len, FALSE);
913 silc_buffer_free(packet);
916 if (server->server_type == SILC_ROUTER &&
918 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
921 protocol->state = SILC_PROTOCOL_STATE_END;
923 ctx->sessions = silc_realloc(ctx->sessions,
924 sizeof(*ctx->sessions) *
925 (ctx->sessions_count + 1));
926 ctx->sessions[ctx->sessions_count].session = ctx->session;
927 ctx->sessions_count++;
932 if (ctx->responder == FALSE) {
935 /* We should have received CONNECTED packet */
936 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
937 SILC_LOG_DEBUG(("Bad resume router packet"));
941 SILC_LOG_DEBUG(("********************************"));
942 SILC_LOG_DEBUG(("Received CONNECTED packet, session %d", ctx->session));
944 for (i = 0; i < ctx->sessions_count; i++) {
945 if (ctx->sessions[i].session == ctx->session) {
946 ctx->sessions[i].connected = TRUE;
951 for (i = 0; i < ctx->sessions_count; i++) {
952 if (!ctx->sessions[i].connected)
956 SILC_LOG_DEBUG(("********************************"));
957 SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
959 /* Send with a timeout */
960 silc_schedule_task_add(server->schedule, 0,
961 silc_server_backup_send_resumed,
962 protocol, 1, 0, SILC_TASK_TIMEOUT,
963 SILC_TASK_PRI_NORMAL);
968 /* We should have been received ENDING packet */
969 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
970 SILC_LOG_DEBUG(("Bad resume router packet"));
974 SILC_LOG_DEBUG(("********************************"));
975 SILC_LOG_DEBUG(("Received ENDING packet, sending RESUMED packets"));
977 /* This state is received by the primary router but also servers
978 and perhaps other routers so check that if we are the primary
979 router of the cell then start sending RESUMED packets. If we
980 are normal server or one of those other routers then procede
982 if (server->router &&
983 !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
984 silc_server_config_is_primary_route(server)) {
985 /* We'll wait for RESUMED packet */
986 protocol->state = SILC_PROTOCOL_STATE_END;
990 /* Switch announced informations to our primary router of using the
992 silc_server_update_servers_by_server(server, ctx->sock->user_data,
994 silc_server_update_clients_by_server(server, ctx->sock->user_data,
995 server->router, TRUE, FALSE);
996 if (server->server_type == SILC_SERVER)
997 silc_server_update_channels_by_server(server, ctx->sock->user_data,
1000 packet = silc_buffer_alloc(2);
1001 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1003 /* We are the primary router, start sending RESUMED packets. */
1004 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1005 if (silc_idcache_list_first(list, &id_cache)) {
1007 server_entry = (SilcServerEntry)id_cache->context;
1008 if (!server_entry || (server_entry == server->id_entry) ||
1009 !server_entry->connection || !server_entry->data.send_key) {
1010 if (!silc_idcache_list_next(list, &id_cache))
1016 SILC_LOG_DEBUG(("********************************"));
1017 SILC_LOG_DEBUG(("RESUMED packet (local)"));
1019 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1021 /* This connection is performing this protocol too now */
1022 ((SilcSocketConnection)server_entry->connection)->protocol =
1025 if (server_entry->server_type == SILC_ROUTER)
1026 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1028 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1029 silc_server_packet_send(server, server_entry->connection,
1030 SILC_PACKET_RESUME_ROUTER, 0,
1031 packet->data, packet->len, FALSE);
1033 if (!silc_idcache_list_next(list, &id_cache))
1038 silc_idcache_list_free(list);
1041 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1042 if (silc_idcache_list_first(list, &id_cache)) {
1044 server_entry = (SilcServerEntry)id_cache->context;
1045 if (!server_entry || (server_entry == server->id_entry) ||
1046 !server_entry->connection || !server_entry->data.send_key) {
1047 if (!silc_idcache_list_next(list, &id_cache))
1053 SILC_LOG_DEBUG(("********************************"));
1054 SILC_LOG_DEBUG(("RESUMED packet (global)"));
1056 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1058 /* This connection is performing this protocol too now */
1059 ((SilcSocketConnection)server_entry->connection)->protocol =
1062 if (server_entry->server_type == SILC_ROUTER)
1063 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1065 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1066 silc_server_packet_send(server, server_entry->connection,
1067 SILC_PACKET_RESUME_ROUTER, 0,
1068 packet->data, packet->len, FALSE);
1070 if (!silc_idcache_list_next(list, &id_cache))
1075 silc_idcache_list_free(list);
1078 silc_buffer_free(packet);
1080 SILC_LOG_INFO(("We are now the primary router of our cell again"));
1082 /* For us this is the end of this protocol. */
1083 if (protocol->final_callback)
1084 silc_protocol_execute_final(protocol, server->schedule);
1086 silc_protocol_free(protocol);
1090 case SILC_PROTOCOL_STATE_END:
1092 SilcIDListData idata;
1093 SilcServerEntry router, backup_router;
1095 /* We should have been received RESUMED packet from our primary
1097 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1098 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1099 SILC_LOG_DEBUG(("Bad resume router packet"));
1103 SILC_LOG_DEBUG(("********************************"));
1104 SILC_LOG_DEBUG(("Received RESUMED packet"));
1106 /* We have now new primary router. All traffic goes there from now on. */
1107 if (server->backup_router)
1108 server->server_type = SILC_BACKUP_ROUTER;
1110 router = (SilcServerEntry)ctx->sock->user_data;
1111 if (silc_server_backup_replaced_get(server, router->id,
1114 if (backup_router == server->router) {
1115 server->id_entry->router = router;
1116 server->router = router;
1117 SILC_LOG_INFO(("Switching back to primary router %s",
1118 server->router->server_name));
1119 SILC_LOG_DEBUG(("Switching back to primary router %s",
1120 server->router->server_name));
1121 idata = (SilcIDListData)server->router;
1122 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1124 SILC_LOG_INFO(("Resuming the use of router %s",
1125 router->server_name));
1126 SILC_LOG_DEBUG(("Resuming the use of router %s",
1127 router->server_name));
1128 idata = (SilcIDListData)router;
1129 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1132 /* Update the client entries of the backup router to the new
1134 silc_server_update_servers_by_server(server, backup_router, router);
1135 silc_server_update_clients_by_server(server, backup_router,
1136 router, TRUE, FALSE);
1137 if (server->server_type == SILC_SERVER)
1138 silc_server_update_channels_by_server(server, backup_router, router);
1139 silc_server_backup_replaced_del(server, backup_router);
1140 silc_server_backup_add(server, backup_router,
1141 ctx->sock->ip, ctx->sock->port,
1142 backup_router->server_type != SILC_ROUTER ?
1145 /* Announce all of our information to the router. */
1146 if (server->server_type == SILC_ROUTER)
1147 silc_server_announce_servers(server, FALSE, 0, router->connection);
1149 /* Announce our clients and channels to the router */
1150 silc_server_announce_clients(server, 0, router->connection);
1151 silc_server_announce_channels(server, 0, router->connection);
1154 /* Protocol has ended, call the final callback */
1155 if (protocol->final_callback)
1156 silc_protocol_execute_final(protocol, server->schedule);
1158 silc_protocol_free(protocol);
1162 case SILC_PROTOCOL_STATE_ERROR:
1163 /* Protocol has ended, call the final callback */
1164 if (protocol->final_callback)
1165 silc_protocol_execute_final(protocol, server->schedule);
1167 silc_protocol_free(protocol);
1170 case SILC_PROTOCOL_STATE_FAILURE:
1171 /* Protocol has ended, call the final callback */
1172 if (protocol->final_callback)
1173 silc_protocol_execute_final(protocol, server->schedule);
1175 silc_protocol_free(protocol);
1178 case SILC_PROTOCOL_STATE_UNKNOWN:
1183 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1185 SilcProtocol protocol = (SilcProtocol)context;
1186 SilcServerBackupProtocolContext ctx = protocol->context;
1187 SilcServer server = ctx->server;
1188 SilcServerEntry server_entry;
1189 SilcSocketConnection sock;
1190 SilcIDCacheList list;
1191 SilcIDCacheEntry id_cache;
1193 SILC_LOG_DEBUG(("Start"));
1195 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1196 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1197 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1200 /* Remove this protocol from all server entries that has it */
1201 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1202 if (silc_idcache_list_first(list, &id_cache)) {
1204 server_entry = (SilcServerEntry)id_cache->context;
1205 sock = (SilcSocketConnection)server_entry->connection;
1207 if (sock->protocol == protocol) {
1208 sock->protocol = NULL;
1210 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1211 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1214 if (!silc_idcache_list_next(list, &id_cache))
1218 silc_idcache_list_free(list);
1221 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1222 if (silc_idcache_list_first(list, &id_cache)) {
1224 server_entry = (SilcServerEntry)id_cache->context;
1225 sock = (SilcSocketConnection)server_entry->connection;
1227 if (sock->protocol == protocol) {
1228 sock->protocol = NULL;
1230 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1231 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1234 if (!silc_idcache_list_next(list, &id_cache))
1238 silc_idcache_list_free(list);
1241 if (ctx->sock->protocol)
1242 ctx->sock->protocol = NULL;
1243 silc_protocol_free(protocol);
1244 silc_free(ctx->sessions);