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;
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;
527 SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
528 sconn->remote_port));
530 /* Connect to remote host */
531 sock = silc_net_create_connection(server->config->server_info->server_ip,
535 silc_schedule_task_add(server->schedule, 0,
536 silc_server_backup_connect_to_router,
537 context, 5, 0, SILC_TASK_TIMEOUT,
538 SILC_TASK_PRI_NORMAL);
542 /* Continue with key exchange protocol */
543 silc_server_start_key_exchange(server, sconn, sock);
546 /* Constantly tries to reconnect to a primary router indicated by the
547 `ip' and `port'. The `connected' callback will be called when the
548 connection is created. */
550 void silc_server_backup_reconnect(SilcServer server,
551 const char *ip, SilcUInt16 port,
552 SilcServerConnectRouterCallback callback,
555 SilcServerConnection sconn;
557 sconn = silc_calloc(1, sizeof(*sconn));
558 sconn->server = server;
559 sconn->remote_host = strdup(ip);
560 sconn->remote_port = port;
561 sconn->callback = callback;
562 sconn->callback_context = context;
563 silc_schedule_task_add(server->schedule, 0,
564 silc_server_backup_connect_to_router,
565 sconn, 1, 0, SILC_TASK_TIMEOUT,
566 SILC_TASK_PRI_NORMAL);
569 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
571 SilcServerBackupProtocolContext proto_ctx =
572 (SilcServerBackupProtocolContext)context;
573 SilcServer server = proto_ctx->server;
574 SilcSocketConnection sock = proto_ctx->sock;
576 SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
578 /* Run the backup resuming protocol */
579 silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
580 &sock->protocol, proto_ctx,
581 silc_server_protocol_backup_done);
582 silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
585 /* Called when we've established connection back to our primary router
586 when we've acting as backup router and have replaced the primary router
587 in the cell. This function will start the backup resuming protocol. */
589 void silc_server_backup_connected(SilcServer server,
590 SilcServerEntry server_entry,
593 SilcServerBackupProtocolContext proto_ctx;
594 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
596 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
597 proto_ctx->server = server;
598 proto_ctx->sock = sock;
599 proto_ctx->responder = FALSE;
600 proto_ctx->type = SILC_SERVER_BACKUP_START;
601 proto_ctx->start = time(0);
603 /* Start through scheduler */
604 silc_schedule_task_add(server->schedule, 0,
605 silc_server_backup_connected_later,
608 SILC_TASK_PRI_NORMAL);
611 /* Called when normal server has connected to its primary router after
612 backup router has sent the START packet in reusming protocol. We will
613 move the protocol context from the backup router connection to the
616 static void silc_server_backup_connect_primary(SilcServer server,
617 SilcServerEntry server_entry,
620 SilcSocketConnection backup_router = (SilcSocketConnection)context;
621 SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
622 SilcIDListData idata = (SilcIDListData)server_entry;
623 SilcServerBackupProtocolContext ctx =
624 (SilcServerBackupProtocolContext)backup_router->protocol->context;
627 SILC_LOG_DEBUG(("Start"));
629 SILC_LOG_DEBUG(("********************************"));
630 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
632 /* Send the CONNECTED packet back to the backup router. */
633 buffer = silc_buffer_alloc(2);
634 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
635 silc_buffer_format(buffer,
636 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
637 SILC_STR_UI_CHAR(ctx->session),
639 silc_server_packet_send(server, backup_router,
640 SILC_PACKET_RESUME_ROUTER, 0,
641 buffer->data, buffer->len, FALSE);
642 silc_buffer_free(buffer);
644 /* The primary connection is disabled until it sends the RESUMED packet
646 idata->status |= SILC_IDLIST_STATUS_DISABLED;
648 /* Move this protocol context from this backup router connection to
649 the primary router connection since it will send the subsequent
650 packets in this protocol. We don't talk with backup router
652 sock->protocol = backup_router->protocol;
653 ctx->sock = (SilcSocketConnection)server_entry->connection;
654 backup_router->protocol = NULL;
657 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
659 SilcProtocol protocol = (SilcProtocol)context;
660 SilcServerBackupProtocolContext ctx = protocol->context;
661 SilcServer server = ctx->server;
665 for (i = 0; i < ctx->sessions_count; i++)
666 if (ctx->sessions[i].server_entry == ctx->sock->user_data)
667 ctx->session = ctx->sessions[i].session;
669 /* We've received all the CONNECTED packets and now we'll send the
670 ENDING packet to the new primary router. */
671 packet = silc_buffer_alloc(2);
672 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
673 silc_buffer_format(packet,
674 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
675 SILC_STR_UI_CHAR(ctx->session),
677 silc_server_packet_send(server, ctx->sock,
678 SILC_PACKET_RESUME_ROUTER, 0,
679 packet->data, packet->len, FALSE);
680 silc_buffer_free(packet);
682 protocol->state = SILC_PROTOCOL_STATE_END;
685 /* Resume protocol with RESUME_ROUTER packet:
687 SILC_PACKET_RESUME_ROUTER:
689 <SilcUInt8 type> <SilcUInt8 Session ID>
691 <type> = the protocol opcode
692 <Session ID> = Identifier for this packet and any subsequent reply
693 packets must include this identifier.
697 1 = To router: Comensing backup resuming protocol. This will
698 indicate that the sender is backup router acting as primary
699 and the receiver is primary router that has been replaced by
702 To server. Comensing backup resuming protocol. This will
703 indicate that the sender is backup router and the receiver
704 must reconnect to the real primary router of the cell.
706 2 = To Router: Comesning backup resuming protocol in another
707 cell. The receiver will connect to its primary router
708 (the router that is now online again) but will not use
709 the link. If the receiver is not configured to connect
710 to any router it does as locally configured. The sender
711 is always backup router.
713 To server: this is never sent to server.
715 3 = To backup router: Sender is normal server or router and it
716 tells to backup router that they have connected to the
717 primary router. Backup router never sends this type.
719 4 = To router: Ending backup resuming protocol. This is sent
720 to the real primary router to tell that it can take over
721 the task as being primary router.
723 To server: same as sending for router.
725 Backup router sends this also to the primary route but only
726 after it has sent them to normal servers and has purged all
727 traffic coming from normal servers.
729 5 = To router: Sender is the real primary router after it has
730 received type 4 from backup router. To tell that it is again
731 primary router of the cell.
733 20 = To router: This is sent only when router is connecting to
734 another router and has been replaced by an backup router.
735 The sender knows that the connectee has been replaced.
739 /* Backup resuming protocol. This protocol is executed when the primary
740 router wants to resume its position as being primary router. */
742 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
744 SilcProtocol protocol = (SilcProtocol)context;
745 SilcServerBackupProtocolContext ctx = protocol->context;
746 SilcServer server = ctx->server;
748 SilcIDCacheList list;
749 SilcIDCacheEntry id_cache;
750 SilcServerEntry server_entry;
753 SILC_LOG_DEBUG(("Start"));
755 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
756 protocol->state = SILC_PROTOCOL_STATE_START;
758 SILC_LOG_DEBUG(("State=%d", protocol->state));
760 switch(protocol->state) {
761 case SILC_PROTOCOL_STATE_START:
762 if (ctx->responder == FALSE) {
763 /* Initiator of the protocol. We are backup router */
765 packet = silc_buffer_alloc(2);
766 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
768 SILC_LOG_DEBUG(("********************************"));
769 SILC_LOG_DEBUG(("Sending START packets"));
771 /* Send the START packet to primary router and normal servers. */
772 if (silc_idcache_get_all(server->local_list->servers, &list)) {
773 if (silc_idcache_list_first(list, &id_cache)) {
775 server_entry = (SilcServerEntry)id_cache->context;
776 if (!server_entry || (server_entry == server->id_entry) ||
777 !server_entry->connection || !server_entry->data.send_key ||
778 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
779 if (!silc_idcache_list_next(list, &id_cache))
785 ctx->sessions = silc_realloc(ctx->sessions,
786 sizeof(*ctx->sessions) *
787 (ctx->sessions_count + 1));
788 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
789 ctx->sessions[ctx->sessions_count].connected = FALSE;
790 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
792 SILC_LOG_DEBUG(("********************************"));
793 SILC_LOG_DEBUG(("START (local) for session %d",
794 ctx->sessions_count));
796 /* This connection is performing this protocol too now */
797 ((SilcSocketConnection)server_entry->connection)->protocol =
800 if (server_entry->server_type == SILC_ROUTER)
801 packet->data[0] = SILC_SERVER_BACKUP_START;
803 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
804 packet->data[1] = ctx->sessions_count;
805 silc_server_packet_send(server, server_entry->connection,
806 SILC_PACKET_RESUME_ROUTER, 0,
807 packet->data, packet->len, FALSE);
808 ctx->sessions_count++;
810 if (!silc_idcache_list_next(list, &id_cache))
815 silc_idcache_list_free(list);
818 if (silc_idcache_get_all(server->global_list->servers, &list)) {
819 if (silc_idcache_list_first(list, &id_cache)) {
821 server_entry = (SilcServerEntry)id_cache->context;
822 if (!server_entry || (server_entry == server->id_entry) ||
823 !server_entry->connection || !server_entry->data.send_key ||
824 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
825 if (!silc_idcache_list_next(list, &id_cache))
831 ctx->sessions = silc_realloc(ctx->sessions,
832 sizeof(*ctx->sessions) *
833 (ctx->sessions_count + 1));
834 ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
835 ctx->sessions[ctx->sessions_count].connected = FALSE;
836 ctx->sessions[ctx->sessions_count].server_entry = server_entry;
838 SILC_LOG_DEBUG(("********************************"));
839 SILC_LOG_DEBUG(("START (global) for session %d",
840 ctx->sessions_count));
842 /* This connection is performing this protocol too now */
843 ((SilcSocketConnection)server_entry->connection)->protocol =
846 if (server_entry->server_type == SILC_ROUTER)
847 packet->data[0] = SILC_SERVER_BACKUP_START;
849 packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
850 packet->data[1] = ctx->sessions_count;
851 silc_server_packet_send(server, server_entry->connection,
852 SILC_PACKET_RESUME_ROUTER, 0,
853 packet->data, packet->len, FALSE);
854 ctx->sessions_count++;
856 if (!silc_idcache_list_next(list, &id_cache))
861 silc_idcache_list_free(list);
864 silc_buffer_free(packet);
866 /* Announce all of our information */
867 silc_server_announce_servers(server, TRUE, 0, ctx->sock);
868 silc_server_announce_clients(server, 0, ctx->sock);
869 silc_server_announce_channels(server, 0, ctx->sock);
873 /* Responder of the protocol. */
874 SilcServerConfigRouter *primary;
876 /* We should have received START or START_GLOBAL packet */
877 if (ctx->type != SILC_SERVER_BACKUP_START &&
878 ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
879 SILC_LOG_DEBUG(("Bad resume router packet"));
883 SILC_LOG_DEBUG(("********************************"));
884 SILC_LOG_DEBUG(("Received START packet, reconnecting to router"));
886 /* Connect to the primary router that was down that is now supposed
887 to be back online. We send the CONNECTED packet after we've
888 established the connection to the primary router. */
889 primary = silc_server_config_get_primary_router(server);
890 if (primary && server->backup_primary) {
891 silc_server_backup_reconnect(server,
892 primary->host, primary->port,
893 silc_server_backup_connect_primary,
896 /* Nowhere to connect just return the CONNECTED packet */
898 SILC_LOG_DEBUG(("********************************"));
899 SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
901 /* Send the CONNECTED packet back to the backup router. */
902 packet = silc_buffer_alloc(2);
903 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
904 silc_buffer_format(packet,
905 SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
906 SILC_STR_UI_CHAR(ctx->session),
908 silc_server_packet_send(server, ctx->sock,
909 SILC_PACKET_RESUME_ROUTER, 0,
910 packet->data, packet->len, FALSE);
911 silc_buffer_free(packet);
914 if (server->server_type == SILC_ROUTER &&
916 server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
919 protocol->state = SILC_PROTOCOL_STATE_END;
921 ctx->sessions = silc_realloc(ctx->sessions,
922 sizeof(*ctx->sessions) *
923 (ctx->sessions_count + 1));
924 ctx->sessions[ctx->sessions_count].session = ctx->session;
925 ctx->sessions_count++;
930 if (ctx->responder == FALSE) {
933 /* We should have received CONNECTED packet */
934 if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
935 SILC_LOG_DEBUG(("Bad resume router packet"));
939 SILC_LOG_DEBUG(("********************************"));
940 SILC_LOG_DEBUG(("Received CONNECTED packet, session %d", ctx->session));
942 for (i = 0; i < ctx->sessions_count; i++) {
943 if (ctx->sessions[i].session == ctx->session) {
944 ctx->sessions[i].connected = TRUE;
949 for (i = 0; i < ctx->sessions_count; i++) {
950 if (!ctx->sessions[i].connected)
954 SILC_LOG_DEBUG(("********************************"));
955 SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
957 /* Send with a timeout */
958 silc_schedule_task_add(server->schedule, 0,
959 silc_server_backup_send_resumed,
960 protocol, 1, 0, SILC_TASK_TIMEOUT,
961 SILC_TASK_PRI_NORMAL);
966 /* We should have been received ENDING packet */
967 if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
968 SILC_LOG_DEBUG(("Bad resume router packet"));
972 SILC_LOG_DEBUG(("********************************"));
973 SILC_LOG_DEBUG(("Received ENDING packet, sending RESUMED packets"));
975 /* This state is received by the primary router but also servers
976 and perhaps other routers so check that if we are the primary
977 router of the cell then start sending RESUMED packets. If we
978 are normal server or one of those other routers then procede
980 if (server->router &&
981 !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
982 silc_server_config_is_primary_route(server)) {
983 /* We'll wait for RESUMED packet */
984 protocol->state = SILC_PROTOCOL_STATE_END;
988 /* Switch announced informations to our primary router of using the
990 silc_server_update_servers_by_server(server, ctx->sock->user_data,
992 silc_server_update_clients_by_server(server, ctx->sock->user_data,
993 server->router, TRUE, FALSE);
994 if (server->server_type == SILC_SERVER)
995 silc_server_update_channels_by_server(server, ctx->sock->user_data,
998 packet = silc_buffer_alloc(2);
999 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1001 /* We are the primary router, start sending RESUMED packets. */
1002 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1003 if (silc_idcache_list_first(list, &id_cache)) {
1005 server_entry = (SilcServerEntry)id_cache->context;
1006 if (!server_entry || (server_entry == server->id_entry) ||
1007 !server_entry->connection || !server_entry->data.send_key) {
1008 if (!silc_idcache_list_next(list, &id_cache))
1014 SILC_LOG_DEBUG(("********************************"));
1015 SILC_LOG_DEBUG(("RESUMED packet (local)"));
1017 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1019 /* This connection is performing this protocol too now */
1020 ((SilcSocketConnection)server_entry->connection)->protocol =
1023 if (server_entry->server_type == SILC_ROUTER)
1024 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1026 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1027 silc_server_packet_send(server, server_entry->connection,
1028 SILC_PACKET_RESUME_ROUTER, 0,
1029 packet->data, packet->len, FALSE);
1031 if (!silc_idcache_list_next(list, &id_cache))
1036 silc_idcache_list_free(list);
1039 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1040 if (silc_idcache_list_first(list, &id_cache)) {
1042 server_entry = (SilcServerEntry)id_cache->context;
1043 if (!server_entry || (server_entry == server->id_entry) ||
1044 !server_entry->connection || !server_entry->data.send_key) {
1045 if (!silc_idcache_list_next(list, &id_cache))
1051 SILC_LOG_DEBUG(("********************************"));
1052 SILC_LOG_DEBUG(("RESUMED packet (global)"));
1054 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1056 /* This connection is performing this protocol too now */
1057 ((SilcSocketConnection)server_entry->connection)->protocol =
1060 if (server_entry->server_type == SILC_ROUTER)
1061 packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1063 packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1064 silc_server_packet_send(server, server_entry->connection,
1065 SILC_PACKET_RESUME_ROUTER, 0,
1066 packet->data, packet->len, FALSE);
1068 if (!silc_idcache_list_next(list, &id_cache))
1073 silc_idcache_list_free(list);
1076 silc_buffer_free(packet);
1078 SILC_LOG_INFO(("We are now the primary router of our cell again"));
1080 /* For us this is the end of this protocol. */
1081 if (protocol->final_callback)
1082 silc_protocol_execute_final(protocol, server->schedule);
1084 silc_protocol_free(protocol);
1088 case SILC_PROTOCOL_STATE_END:
1090 SilcIDListData idata;
1091 SilcServerEntry router, backup_router;
1093 /* We should have been received RESUMED packet from our primary
1095 if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1096 ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1097 SILC_LOG_DEBUG(("Bad resume router packet"));
1101 SILC_LOG_DEBUG(("********************************"));
1102 SILC_LOG_DEBUG(("Received RESUMED packet"));
1104 /* We have now new primary router. All traffic goes there from now on. */
1105 if (server->backup_router)
1106 server->server_type = SILC_BACKUP_ROUTER;
1108 router = (SilcServerEntry)ctx->sock->user_data;
1109 if (silc_server_backup_replaced_get(server, router->id,
1112 if (backup_router == server->router) {
1113 server->id_entry->router = router;
1114 server->router = router;
1115 SILC_LOG_INFO(("Switching back to primary router %s",
1116 server->router->server_name));
1117 SILC_LOG_DEBUG(("Switching back to primary router %s",
1118 server->router->server_name));
1119 idata = (SilcIDListData)server->router;
1120 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1122 SILC_LOG_INFO(("Resuming the use of router %s",
1123 router->server_name));
1124 SILC_LOG_DEBUG(("Resuming the use of router %s",
1125 router->server_name));
1126 idata = (SilcIDListData)router;
1127 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1130 /* Update the client entries of the backup router to the new
1132 silc_server_update_servers_by_server(server, backup_router, router);
1133 silc_server_update_clients_by_server(server, backup_router,
1134 router, TRUE, FALSE);
1135 if (server->server_type == SILC_SERVER)
1136 silc_server_update_channels_by_server(server, backup_router, router);
1137 silc_server_backup_replaced_del(server, backup_router);
1138 silc_server_backup_add(server, backup_router,
1139 ctx->sock->ip, ctx->sock->port,
1140 backup_router->server_type != SILC_ROUTER ?
1143 /* Announce all of our information to the router. */
1144 if (server->server_type == SILC_ROUTER)
1145 silc_server_announce_servers(server, FALSE, 0, router->connection);
1147 /* Announce our clients and channels to the router */
1148 silc_server_announce_clients(server, 0, router->connection);
1149 silc_server_announce_channels(server, 0, router->connection);
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);
1160 case SILC_PROTOCOL_STATE_ERROR:
1161 /* Protocol has ended, call the final callback */
1162 if (protocol->final_callback)
1163 silc_protocol_execute_final(protocol, server->schedule);
1165 silc_protocol_free(protocol);
1168 case SILC_PROTOCOL_STATE_FAILURE:
1169 /* Protocol has ended, call the final callback */
1170 if (protocol->final_callback)
1171 silc_protocol_execute_final(protocol, server->schedule);
1173 silc_protocol_free(protocol);
1176 case SILC_PROTOCOL_STATE_UNKNOWN:
1181 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1183 SilcProtocol protocol = (SilcProtocol)context;
1184 SilcServerBackupProtocolContext ctx = protocol->context;
1185 SilcServer server = ctx->server;
1186 SilcServerEntry server_entry;
1187 SilcSocketConnection sock;
1188 SilcIDCacheList list;
1189 SilcIDCacheEntry id_cache;
1191 SILC_LOG_DEBUG(("Start"));
1193 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1194 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1195 SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1198 /* Remove this protocol from all server entries that has it */
1199 if (silc_idcache_get_all(server->local_list->servers, &list)) {
1200 if (silc_idcache_list_first(list, &id_cache)) {
1202 server_entry = (SilcServerEntry)id_cache->context;
1203 sock = (SilcSocketConnection)server_entry->connection;
1205 if (sock->protocol == protocol) {
1206 sock->protocol = NULL;
1208 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1209 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1212 if (!silc_idcache_list_next(list, &id_cache))
1216 silc_idcache_list_free(list);
1219 if (silc_idcache_get_all(server->global_list->servers, &list)) {
1220 if (silc_idcache_list_first(list, &id_cache)) {
1222 server_entry = (SilcServerEntry)id_cache->context;
1223 sock = (SilcSocketConnection)server_entry->connection;
1225 if (sock->protocol == protocol) {
1226 sock->protocol = NULL;
1228 if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1229 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1232 if (!silc_idcache_list_next(list, &id_cache))
1236 silc_idcache_list_free(list);
1239 if (ctx->sock->protocol)
1240 ctx->sock->protocol = NULL;
1241 silc_protocol_free(protocol);
1242 silc_free(ctx->sessions);