X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fserver_backup.c;h=5888909c6a1a63d3716a345c9d98d22f82a2b8d7;hb=a818c5b5411bbc4436d1c5f011236985c96bb787;hp=96f9c33f702ee2650f0e6c6e9d99b7e1f8ca1808;hpb=26516272f6e9e47c6472efa50493a6a1044c02ac;p=silc.git diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index 96f9c33f..5888909c 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -26,6 +26,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done); /* Backup router */ typedef struct { SilcServerEntry server; + SilcIDIP ip; + SilcUInt16 port; bool local; } SilcServerBackupEntry; @@ -33,20 +35,20 @@ typedef struct { by backup router. */ typedef struct { SilcIDIP ip; - uint16 port; + SilcUInt16 port; SilcServerEntry server; /* Backup router that replaced the primary */ } SilcServerBackupReplaced; /* Backup context */ struct SilcServerBackupStruct { SilcServerBackupEntry *servers; - uint32 servers_count; + SilcUInt32 servers_count; SilcServerBackupReplaced **replaced; - uint32 replaced_count; + SilcUInt32 replaced_count; }; typedef struct { - uint8 session; + SilcUInt8 session; bool connected; SilcServerEntry server_entry; } SilcServerBackupProtocolSession; @@ -56,23 +58,29 @@ typedef struct { SilcServer server; SilcSocketConnection sock; bool responder; - uint8 type; - uint8 session; + SilcUInt8 type; + SilcUInt8 session; SilcServerBackupProtocolSession *sessions; - uint32 sessions_count; + SilcUInt32 sessions_count; long start; } *SilcServerBackupProtocolContext; -/* Sets the `backup_server' to be one of our backup router. This can be - called multiple times to set multiple backup routers. If `local' is - TRUE then the `backup_server' is in the local cell, if FALSE it is - in some other cell. */ +/* Adds the `backup_server' to be one of our backup router. This can be + called multiple times to set multiple backup routers. The `ip' and `port' + is the IP and port that the `backup_router' will replace if the `ip' + will become unresponsive. If `local' is TRUE then the `backup_server' is + in the local cell, if FALSE it is in some other cell. */ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server, - bool local) + const char *ip, int port, bool local) { int i; + SILC_LOG_DEBUG(("Start")); + + if (!ip) + return; + if (!server->backup) server->backup = silc_calloc(1, sizeof(*server->backup)); @@ -80,6 +88,11 @@ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server, if (!server->backup->servers[i].server) { server->backup->servers[i].server = backup_server; server->backup->servers[i].local = local; + memset(server->backup->servers[i].ip.data, 0, + sizeof(server->backup->servers[i].ip.data)); + silc_net_addr2bin(ip, server->backup->servers[i].ip.data, + sizeof(server->backup->servers[i].ip.data)); + //server->backup->servers[i].port = port; return; } } @@ -90,38 +103,46 @@ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server, (i + 1)); server->backup->servers[i].server = backup_server; server->backup->servers[i].local = local; + memset(server->backup->servers[i].ip.data, 0, + sizeof(server->backup->servers[i].ip.data)); + silc_net_addr2bin(ip, server->backup->servers[i].ip.data, + sizeof(server->backup->servers[i].ip.data)); + //server->backup->servers[i].port = server_id->port; server->backup->servers_count++; } -/* Returns the first backup router context. Returns NULL if we do not have - any backup servers. */ +/* Returns backup router for IP and port in `replacing' or NULL if there + does not exist backup router. */ -SilcServerEntry silc_server_backup_get(SilcServer server) +SilcServerEntry silc_server_backup_get(SilcServer server, + SilcServerID *server_id) { - SilcServerEntry backup_router; int i; + SILC_LOG_DEBUG(("Start")); + if (!server->backup) return NULL; for (i = 0; i < server->backup->servers_count; i++) { - if (server->backup->servers[i].server) { - backup_router = server->backup->servers[i].server; - server->backup->servers[i].server = NULL; - return backup_router; - } + SILC_LOG_HEXDUMP(("IP"), server_id->ip.data, 16); + SILC_LOG_HEXDUMP(("IP"), server->backup->servers[i].ip.data, 16); + if (server->backup->servers[i].server && + !memcmp(&server->backup->servers[i].ip, &server_id->ip.data, + sizeof(server_id->ip.data))) + return server->backup->servers[i].server; } return NULL; } -/* Deletes the backup server `server_entry. */ - -void silc_server_backup_del(SilcServer server, - SilcServerEntry server_entry) +/* Deletes the backup server `server_entry'. */ +void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry) { int i; + SILC_LOG_DEBUG(("Start")); + if (!server->backup) return ; @@ -145,6 +166,8 @@ void silc_server_backup_replaced_add(SilcServer server, int i; SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));; + SILC_LOG_DEBUG(("Start")); + if (!server->backup) server->backup = silc_calloc(1, sizeof(*server->backup)); if (!server->backup->replaced) { @@ -186,7 +209,9 @@ bool silc_server_backup_replaced_get(SilcServer server, { int i; - SILC_LOG_DEBUG(("***********************************************")); + SILC_LOG_DEBUG(("Start")); + + SILC_LOG_DEBUG(("*************************************")); if (!server->backup || !server->backup->replaced) return FALSE; @@ -197,8 +222,8 @@ bool silc_server_backup_replaced_get(SilcServer server, SILC_LOG_HEXDUMP(("IP"), server_id->ip.data, server_id->ip.data_len); SILC_LOG_HEXDUMP(("IP"), server->backup->replaced[i]->ip.data, server->backup->replaced[i]->ip.data_len); - if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip, - sizeof(server_id->ip))) { + if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip.data, + sizeof(server_id->ip.data))) { if (server_entry) *server_entry = server->backup->replaced[i]->server; SILC_LOG_DEBUG(("REPLACED")); @@ -217,6 +242,8 @@ void silc_server_backup_replaced_del(SilcServer server, { int i; + SILC_LOG_DEBUG(("Start")); + if (!server->backup || !server->backup->replaced) return; @@ -266,7 +293,7 @@ void silc_server_backup_broadcast(SilcServer server, silc_packet_send_prepare(sock, 0, 0, buffer->len); silc_buffer_put(sock->outbuf, buffer->data, buffer->len); - silc_packet_encrypt(idata->send_key, idata->hmac_send, + silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, sock->outbuf, sock->outbuf->len); SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len), @@ -292,7 +319,7 @@ void silc_server_backup_send(SilcServer server, SilcPacketType type, SilcPacketFlags flags, unsigned char *data, - uint32 data_len, + SilcUInt32 data_len, bool force_send, bool local) { @@ -334,7 +361,7 @@ void silc_server_backup_send_dest(SilcServer server, void *dst_id, SilcIdType dst_id_type, unsigned char *data, - uint32 data_len, + SilcUInt32 data_len, bool force_send, bool local) { @@ -373,8 +400,9 @@ void silc_server_backup_resume_router(SilcServer server, SilcSocketConnection sock, SilcPacketContext *packet) { - uint8 type, session; - int ret; + SilcUInt8 type, session; + SilcServerBackupProtocolContext ctx; + int i, ret; if (sock->type == SILC_SOCKET_TYPE_CLIENT || sock->type == SILC_SOCKET_TYPE_UNKNOWN) @@ -389,13 +417,34 @@ void silc_server_backup_resume_router(SilcServer server, if (ret < 0) return; + /* Activate the protocol for this socket if necessary */ + if ((type == SILC_SERVER_BACKUP_RESUMED || + type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) && + sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol && + ((SilcIDListData)sock->user_data)->status & + SILC_IDLIST_STATUS_DISABLED) { + SilcServerEntry backup_router; + + if (silc_server_backup_replaced_get(server, + ((SilcServerEntry)sock-> + user_data)->id, + &backup_router)) { + SilcSocketConnection bsock = + (SilcSocketConnection)backup_router->connection; + if (bsock->protocol && bsock->protocol->protocol && + bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) { + sock->protocol = bsock->protocol; + ctx = sock->protocol->context; + ctx->sock = sock; + } + } + } + /* If the backup resuming protocol is active then process the packet in the protocol. */ if (sock->protocol && sock->protocol->protocol && sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) { - SilcServerBackupProtocolContext ctx = sock->protocol->context; - int i; - + ctx = sock->protocol->context; ctx->type = type; SILC_LOG_DEBUG(("********************************")); @@ -432,6 +481,9 @@ void silc_server_backup_resume_router(SilcServer server, to use it at this moment. */ SilcIDListData idata = (SilcIDListData)sock->user_data; + SILC_LOG_INFO(("We are replaced by an backup router in this cell, will " + "wait until backup resuming protocol is executed")); + SILC_LOG_DEBUG(("We are replaced by an backup router in this cell")); idata->status |= SILC_IDLIST_STATUS_DISABLED; return; @@ -472,13 +524,13 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router) sconn->remote_port)); /* Connect to remote host */ - sock = silc_net_create_connection(server->config->listen_port->local_ip, + sock = silc_net_create_connection(server->config->server_info->server_ip, sconn->remote_port, sconn->remote_host); if (sock < 0) { silc_schedule_task_add(server->schedule, 0, silc_server_backup_connect_to_router, - context, 2, 0, SILC_TASK_TIMEOUT, + context, 5, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); return; } @@ -492,7 +544,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router) connection is created. */ void silc_server_backup_reconnect(SilcServer server, - const char *ip, uint16 port, + const char *ip, SilcUInt16 port, SilcServerConnectRouterCallback callback, void *context) { @@ -506,7 +558,7 @@ void silc_server_backup_reconnect(SilcServer server, sconn->callback_context = context; silc_schedule_task_add(server->schedule, 0, silc_server_backup_connect_to_router, - sconn, 2, 0, SILC_TASK_TIMEOUT, + sconn, 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); } @@ -568,6 +620,8 @@ static void silc_server_backup_connect_primary(SilcServer server, (SilcServerBackupProtocolContext)backup_router->protocol->context; SilcBuffer buffer; + SILC_LOG_DEBUG(("Start")); + SILC_LOG_DEBUG(("********************************")); SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session)); @@ -596,11 +650,39 @@ static void silc_server_backup_connect_primary(SilcServer server, backup_router->protocol = NULL; } +SILC_TASK_CALLBACK(silc_server_backup_send_resumed) +{ + SilcProtocol protocol = (SilcProtocol)context; + SilcServerBackupProtocolContext ctx = protocol->context; + SilcServer server = ctx->server; + SilcBuffer packet; + int i; + + for (i = 0; i < ctx->sessions_count; i++) + if (ctx->sessions[i].server_entry == ctx->sock->user_data) + ctx->session = ctx->sessions[i].session; + + /* We've received all the CONNECTED packets and now we'll send the + ENDING packet to the new primary router. */ + packet = silc_buffer_alloc(2); + silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet)); + silc_buffer_format(packet, + SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING), + SILC_STR_UI_CHAR(ctx->session), + SILC_STR_END); + silc_server_packet_send(server, ctx->sock, + SILC_PACKET_RESUME_ROUTER, 0, + packet->data, packet->len, FALSE); + silc_buffer_free(packet); + + protocol->state = SILC_PROTOCOL_STATE_END; +} + /* Resume protocol with RESUME_ROUTER packet: SILC_PACKET_RESUME_ROUTER: - + = the protocol opcode = Identifier for this packet and any subsequent reply @@ -687,8 +769,55 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { server_entry = (SilcServerEntry)id_cache->context; - if ((server_entry == server->id_entry) || - !server_entry->connection) { + if (!server_entry || (server_entry == server->id_entry) || + !server_entry->connection || !server_entry->data.send_key || + (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) { + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; + } + + ctx->sessions = silc_realloc(ctx->sessions, + sizeof(*ctx->sessions) * + (ctx->sessions_count + 1)); + ctx->sessions[ctx->sessions_count].session = ctx->sessions_count; + ctx->sessions[ctx->sessions_count].connected = FALSE; + ctx->sessions[ctx->sessions_count].server_entry = server_entry; + + SILC_LOG_DEBUG(("********************************")); + SILC_LOG_DEBUG(("START (local) for session %d", + ctx->sessions_count)); + + /* This connection is performing this protocol too now */ + ((SilcSocketConnection)server_entry->connection)->protocol = + protocol; + + if (server_entry->server_type == SILC_ROUTER) + packet->data[0] = SILC_SERVER_BACKUP_START; + else + packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL; + packet->data[1] = ctx->sessions_count; + silc_server_packet_send(server, server_entry->connection, + SILC_PACKET_RESUME_ROUTER, 0, + packet->data, packet->len, FALSE); + ctx->sessions_count++; + + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + + silc_idcache_list_free(list); + } + + if (silc_idcache_get_all(server->global_list->servers, &list)) { + if (silc_idcache_list_first(list, &id_cache)) { + while (id_cache) { + server_entry = (SilcServerEntry)id_cache->context; + if (!server_entry || (server_entry == server->id_entry) || + !server_entry->connection || !server_entry->data.send_key || + (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) { if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -703,7 +832,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) ctx->sessions[ctx->sessions_count].server_entry = server_entry; SILC_LOG_DEBUG(("********************************")); - SILC_LOG_DEBUG(("START for session %d", ctx->sessions_count)); + SILC_LOG_DEBUG(("START (global) for session %d", + ctx->sessions_count)); /* This connection is performing this protocol too now */ ((SilcSocketConnection)server_entry->connection)->protocol = @@ -729,16 +859,15 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) silc_buffer_free(packet); - /* If we are router then announce our possible servers. */ - if (server->server_type == SILC_ROUTER) - silc_server_announce_servers(server, FALSE, 0, ctx->sock); + /* Announce all of our information */ + silc_server_announce_servers(server, TRUE, 0, ctx->sock); silc_server_announce_clients(server, 0, ctx->sock); silc_server_announce_channels(server, 0, ctx->sock); protocol->state++; } else { /* Responder of the protocol. */ - SilcServerConfigSectionServerConnection *primary; + SilcServerConfigRouter *primary; /* We should have received START or START_GLOBAL packet */ if (ctx->type != SILC_SERVER_BACKUP_START && @@ -753,19 +882,12 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) /* Connect to the primary router that was down that is now supposed to be back online. We send the CONNECTED packet after we've established the connection to the primary router. */ - primary = silc_server_config_get_primary_router(server->config); - if (primary) { + primary = silc_server_config_get_primary_router(server); + if (primary && server->backup_primary) { silc_server_backup_reconnect(server, primary->host, primary->port, silc_server_backup_connect_primary, ctx->sock); - if (server->server_type == SILC_ROUTER && - (!server->router || - server->router->data.status & SILC_IDLIST_STATUS_DISABLED)) - protocol->state++; - else - protocol->state = SILC_PROTOCOL_STATE_END; - } else { /* Nowhere to connect just return the CONNECTED packet */ @@ -783,9 +905,15 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) SILC_PACKET_RESUME_ROUTER, 0, packet->data, packet->len, FALSE); silc_buffer_free(packet); - protocol->state++; } + if (server->server_type == SILC_ROUTER && + (!server->router || + server->router->data.status & SILC_IDLIST_STATUS_DISABLED)) + protocol->state++; + else + protocol->state = SILC_PROTOCOL_STATE_END; + ctx->sessions = silc_realloc(ctx->sessions, sizeof(*ctx->sessions) * (ctx->sessions_count + 1)); @@ -822,24 +950,12 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) SILC_LOG_DEBUG(("********************************")); SILC_LOG_DEBUG(("Sending ENDING packet to primary")); - for (i = 0; i < ctx->sessions_count; i++) - if (ctx->sessions[i].server_entry == ctx->sock->user_data) - ctx->session = ctx->sessions[i].session; - - /* We've received all the CONNECTED packets and now we'll send the - ENDING packet to the new primary router. */ - packet = silc_buffer_alloc(2); - silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet)); - silc_buffer_format(packet, - SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING), - SILC_STR_UI_CHAR(ctx->session), - SILC_STR_END); - silc_server_packet_send(server, ctx->sock, - SILC_PACKET_RESUME_ROUTER, 0, - packet->data, packet->len, FALSE); - silc_buffer_free(packet); - - protocol->state = SILC_PROTOCOL_STATE_END; + /* Send with a timeout */ + silc_schedule_task_add(server->schedule, 0, + silc_server_backup_send_resumed, + protocol, 1, 0, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); + return; } else { /* Responder */ @@ -859,16 +975,21 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) to next state. */ if (server->router && !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) && - silc_server_config_is_primary_route(server->config)) { + silc_server_config_is_primary_route(server)) { /* We'll wait for RESUMED packet */ protocol->state = SILC_PROTOCOL_STATE_END; break; } - /* Switch announced informations to our entry instead of using the + /* Switch announced informations to our primary router of using the backup router. */ + silc_server_update_servers_by_server(server, ctx->sock->user_data, + server->router); silc_server_update_clients_by_server(server, ctx->sock->user_data, - server->id_entry, TRUE, FALSE); + server->router, TRUE, FALSE); + if (server->server_type == SILC_SERVER) + silc_server_update_channels_by_server(server, ctx->sock->user_data, + server->router); packet = silc_buffer_alloc(2); silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet)); @@ -878,8 +999,45 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { server_entry = (SilcServerEntry)id_cache->context; - if ((server_entry == server->id_entry) || - !server_entry->connection) { + if (!server_entry || (server_entry == server->id_entry) || + !server_entry->connection || !server_entry->data.send_key) { + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; + } + + SILC_LOG_DEBUG(("********************************")); + SILC_LOG_DEBUG(("RESUMED packet (local)")); + + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + + /* This connection is performing this protocol too now */ + ((SilcSocketConnection)server_entry->connection)->protocol = + protocol; + + if (server_entry->server_type == SILC_ROUTER) + packet->data[0] = SILC_SERVER_BACKUP_RESUMED; + else + packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL; + silc_server_packet_send(server, server_entry->connection, + SILC_PACKET_RESUME_ROUTER, 0, + packet->data, packet->len, FALSE); + + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + + silc_idcache_list_free(list); + } + + if (silc_idcache_get_all(server->global_list->servers, &list)) { + if (silc_idcache_list_first(list, &id_cache)) { + while (id_cache) { + server_entry = (SilcServerEntry)id_cache->context; + if (!server_entry || (server_entry == server->id_entry) || + !server_entry->connection || !server_entry->data.send_key) { if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -887,7 +1045,9 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) } SILC_LOG_DEBUG(("********************************")); - SILC_LOG_DEBUG(("RESUMED packet")); + SILC_LOG_DEBUG(("RESUMED packet (global)")); + + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; /* This connection is performing this protocol too now */ ((SilcSocketConnection)server_entry->connection)->protocol = @@ -911,6 +1071,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) silc_buffer_free(packet); + SILC_LOG_INFO(("We are now the primary router of our cell again")); + /* For us this is the end of this protocol. */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -922,8 +1084,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) case SILC_PROTOCOL_STATE_END: { SilcIDListData idata; - SilcServerEntry primary; - SilcServerEntry backup_router; + SilcServerEntry router, backup_router; /* We should have been received RESUMED packet from our primary router. */ @@ -940,41 +1101,48 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) if (server->backup_router) server->server_type = SILC_BACKUP_ROUTER; - primary = (SilcServerEntry)ctx->sock->user_data; - if (silc_server_backup_replaced_get(server, primary->id, + router = (SilcServerEntry)ctx->sock->user_data; + if (silc_server_backup_replaced_get(server, router->id, &backup_router)) { if (backup_router == server->router) { - server->id_entry->router = ctx->sock->user_data; - server->router = ctx->sock->user_data; + server->id_entry->router = router; + server->router = router; SILC_LOG_INFO(("Switching back to primary router %s", server->router->server_name)); - SILC_LOG_DEBUG(("********************************")); SILC_LOG_DEBUG(("Switching back to primary router %s", server->router->server_name)); idata = (SilcIDListData)server->router; idata->status &= ~SILC_IDLIST_STATUS_DISABLED; - - /* Update the client entries of the backup router to the new - primary router. */ - silc_server_update_clients_by_server(server, backup_router, - primary, TRUE, FALSE); - silc_server_backup_replaced_del(server, backup_router); - silc_server_backup_add(server, backup_router, - backup_router->server_type != SILC_ROUTER ? - TRUE : FALSE); + } else { + SILC_LOG_INFO(("Resuming the use of router %s", + router->server_name)); + SILC_LOG_DEBUG(("Resuming the use of router %s", + router->server_name)); + idata = (SilcIDListData)router; + idata->status &= ~SILC_IDLIST_STATUS_DISABLED; } - /* Announce all of our information to the new primary router. */ + /* Update the client entries of the backup router to the new + router */ + silc_server_update_servers_by_server(server, backup_router, router); + silc_server_update_clients_by_server(server, backup_router, + router, TRUE, FALSE); + if (server->server_type == SILC_SERVER) + silc_server_update_channels_by_server(server, backup_router, router); + silc_server_backup_replaced_del(server, backup_router); + silc_server_backup_add(server, backup_router, + ctx->sock->ip, ctx->sock->port, + backup_router->server_type != SILC_ROUTER ? + TRUE : FALSE); + + /* Announce all of our information to the router. */ if (server->server_type == SILC_ROUTER) - silc_server_announce_servers(server, FALSE, 0, - server->router->connection); - + silc_server_announce_servers(server, FALSE, 0, router->connection); + /* Announce our clients and channels to the router */ - silc_server_announce_clients(server, 0, - server->router->connection); - silc_server_announce_channels(server, 0, - server->router->connection); + silc_server_announce_clients(server, 0, router->connection); + silc_server_announce_channels(server, 0, router->connection); } /* Protocol has ended, call the final callback */ @@ -1023,15 +1191,39 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done) SILC_LOG_ERROR(("Error occurred during backup router resuming protcool")); } + /* Remove this protocol from all server entries that has it */ if (silc_idcache_get_all(server->local_list->servers, &list)) { if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { server_entry = (SilcServerEntry)id_cache->context; sock = (SilcSocketConnection)server_entry->connection; - if (sock->protocol && sock->protocol->protocol && - sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) + if (sock->protocol == protocol) { sock->protocol = NULL; + + if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED) + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + } + + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + silc_idcache_list_free(list); + } + + if (silc_idcache_get_all(server->global_list->servers, &list)) { + if (silc_idcache_list_first(list, &id_cache)) { + while (id_cache) { + server_entry = (SilcServerEntry)id_cache->context; + sock = (SilcSocketConnection)server_entry->connection; + + if (sock->protocol == protocol) { + sock->protocol = NULL; + + if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED) + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + } if (!silc_idcache_list_next(list, &id_cache)) break;