From ccfbb5f7a211591c8e5503c99ac3333f469bbe83 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 27 Jun 2002 12:21:58 +0000 Subject: [PATCH] Fixed notify sending to backup routers, and fixed channel deletion on backup router. --- CHANGES | 15 +++++++++++++++ apps/silcd/packet_receive.c | 24 ++++++++++++++++++++++++ apps/silcd/packet_send.c | 10 ++++++++++ apps/silcd/server.c | 27 +++++++++++++++++---------- apps/silcd/server_internal.h | 1 + apps/silcd/server_util.c | 10 ++++++++-- apps/silcd/serverconfig.c | 25 +++++++++++++++++++++++++ apps/silcd/serverconfig.h | 2 ++ 8 files changed, 102 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index e559274f..09d6d39a 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,21 @@ Thu Jun 27 11:27:07 CEST 2002 Pekka Riikonen directly after backup router has arrived. Affected file silcd/server.c. + * Do not re-create channel keys and send them when removing + clients in server shutdown. Affected files are + silcd/server_internal.h and silcd/server_util.c. + + * Notify distribution to backup routers was missing from + the silc_server_send_notify_dest function which caused + desyncing problems with backup router. Affected file is + silcd/packet_send.c. + + * The client's channel removing was working wrong on + backup router. It assumed that it doesn't know global + information but backup router does know. For this reason + it could remove channel when it wasn't supposed to do that. + Affected file silcd/server.c and silcd/server_util.c. + Wed Jun 26 15:14:12 EEST 2002 Pekka Riikonen * Stop for a couple seconds after badkup router has become diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 33d1bce0..ed8ad2f0 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -2497,6 +2497,30 @@ SilcServerEntry silc_server_new_server(SilcServer server, silc_server_announce_channels(server, 0, sock); } + /* Announce our information to backup router */ + if (new_server->server_type == SILC_BACKUP_ROUTER && + sock->type == SILC_SOCKET_TYPE_SERVER && + server->server_type == SILC_ROUTER) { + silc_server_announce_servers(server, TRUE, 0, sock); + silc_server_announce_clients(server, 0, sock); + silc_server_announce_channels(server, 0, sock); + } + + /* If backup router, mark it as one of ours. This server is considered + to be backup router after this setting. */ + if (new_server->server_type == SILC_BACKUP_ROUTER) { + SilcServerConfigRouter *backup; + backup = silc_server_config_find_backup_conn(server, sock->ip); + if (!backup) + backup = silc_server_config_find_backup_conn(server, sock->hostname); + if (backup) { + /* Add as our backup router */ + silc_server_backup_add(server, new_server, backup->backup_replace_ip, + backup->backup_replace_port, + backup->backup_local); + } + } + /* By default the servers connected to backup router are disabled until backup router has become the primary */ if (server->server_type == SILC_BACKUP_ROUTER && diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 14895b2e..65637c15 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -1494,6 +1494,16 @@ void silc_server_send_notify_dest(SilcServer server, broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, dest_id, dest_id_type, packet->data, packet->len, FALSE); + + /* Send to backup routers if this is being broadcasted to primary + router. The silc_server_backup_send checks further whether to + actually send it or not. */ + if ((broadcast && sock && sock == SILC_PRIMARY_ROUTE(server)) || + (broadcast && !sock && !SILC_PRIMARY_ROUTE(server))) + silc_server_backup_send_dest(server, NULL, SILC_PACKET_NOTIFY, 0, + dest_id, dest_id_type, + packet->data, packet->len, FALSE, TRUE); + silc_buffer_free(packet); va_end(ap); } diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 1f6a7789..cc772361 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -668,6 +668,8 @@ void silc_server_stop(SilcServer server) if (server->schedule) { int i; + server->server_shutdown = TRUE; + /* Close all connections */ for (i = 0; i < server->config->param.connections_max; i++) { if (!server->sockets[i]) @@ -1909,13 +1911,9 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) /* If the incoming connection is router and marked as backup router then add it to be one of our backups */ if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER && backup_router) { - silc_server_backup_add(server, new_server, backup_replace_ip, - backup_replace_port, backup_local); - /* Change it back to SERVER type since that's what it really is. */ if (backup_local) ctx->conn_type = SILC_SOCKET_TYPE_SERVER; - new_server->server_type = SILC_BACKUP_ROUTER; } @@ -3176,7 +3174,7 @@ void silc_server_remove_from_channels(SilcServer server, /* Remove channel if this is last client leaving the channel, unless the channel is permanent. */ - if (server->server_type == SILC_ROUTER && + if (server->server_type != SILC_SERVER && silc_hash_table_count(channel->user_list) < 2) { silc_server_channel_delete(server, channel); continue; @@ -3188,7 +3186,7 @@ void silc_server_remove_from_channels(SilcServer server, /* If there is no global users on the channel anymore mark the channel as local channel. Do not check if the removed client is local client. */ - if (server->server_type != SILC_ROUTER && channel->global_users && + if (server->server_type == SILC_SERVER && channel->global_users && chl->client->router && !silc_server_channel_has_global(channel)) channel->global_users = FALSE; @@ -3205,7 +3203,7 @@ void silc_server_remove_from_channels(SilcServer server, /* If there is not at least one local user on the channel then we don't need the channel entry anymore, we can remove it safely, unless the channel is permanent channel */ - if (server->server_type != SILC_ROUTER && + if (server->server_type == SILC_SERVER && !silc_server_channel_has_local(channel)) { /* Notify about leaving client if this channel has global users. */ if (notify && channel->global_users) @@ -3230,6 +3228,10 @@ void silc_server_remove_from_channels(SilcServer server, signoff_message, signoff_message ? strlen(signoff_message) : 0); + /* Don't create keys if we are shutting down */ + if (server->server_shutdown) + continue; + /* Re-generate channel key if needed */ if (keygen && !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) { if (!silc_server_create_channel_key(server, channel, 0)) @@ -3274,7 +3276,7 @@ bool silc_server_remove_from_one_channel(SilcServer server, /* Remove channel if this is last client leaving the channel, unless the channel is permanent. */ - if (server->server_type == SILC_ROUTER && + if (server->server_type != SILC_SERVER && silc_hash_table_count(channel->user_list) < 2) { silc_server_channel_delete(server, channel); return FALSE; @@ -3286,7 +3288,7 @@ bool silc_server_remove_from_one_channel(SilcServer server, /* If there is no global users on the channel anymore mark the channel as local channel. Do not check if the client is local client. */ - if (server->server_type != SILC_ROUTER && channel->global_users && + if (server->server_type == SILC_SERVER && channel->global_users && chl->client->router && !silc_server_channel_has_global(channel)) channel->global_users = FALSE; @@ -3307,7 +3309,7 @@ bool silc_server_remove_from_one_channel(SilcServer server, /* If there is not at least one local user on the channel then we don't need the channel entry anymore, we can remove it safely, unless the channel is permanent channel */ - if (server->server_type != SILC_ROUTER && + if (server->server_type == SILC_SERVER && !silc_server_channel_has_local(channel)) { /* Notify about leaving client if this channel has global users. */ if (notify && channel->global_users) @@ -3566,6 +3568,10 @@ SILC_TASK_CALLBACK(silc_server_channel_key_rekey) rekey->task = NULL; + /* Return now if we are shutting down */ + if (server->server_shutdown) + return; + if (!silc_server_create_channel_key(server, rekey->channel, rekey->key_len)) return; @@ -3690,6 +3696,7 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server, if (!channel) { SILC_LOG_ERROR(("Received key for non-existent channel %s", silc_id_render(id, SILC_ID_CHANNEL))); + assert(FALSE); goto out; } } diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index f7e70f46..74babfaa 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -83,6 +83,7 @@ struct SilcServerStruct { router to a backup router. */ unsigned int wait_backup : 1; /* Set if we are waiting for backup router to connect to us. */ + unsigned int server_shutdown: 1; /* Set when shutting down */ SilcServerEntry router; /* Pointer to the primary router */ unsigned long router_connect; /* Time when router was connected */ diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index d0157e3a..18381931 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -55,7 +55,7 @@ silc_server_remove_clients_channels(SilcServer server, /* Remove channel if this is last client leaving the channel, unless the channel is permanent. */ - if (server->server_type == SILC_ROUTER && + if (server->server_type != SILC_SERVER && silc_hash_table_count(channel->user_list) < 2) { if (silc_hash_table_find(channels, channel, NULL, NULL)) silc_hash_table_del(channels, channel); @@ -87,7 +87,7 @@ silc_server_remove_clients_channels(SilcServer server, /* If there is not at least one local user on the channel then we don't need the channel entry anymore, we can remove it safely, unless the channel is permanent channel */ - if (server->server_type != SILC_ROUTER && + if (server->server_type == SILC_SERVER && !silc_server_channel_has_local(channel)) { if (silc_hash_table_find(channels, channel, NULL, NULL)) silc_hash_table_del(channels, channel); @@ -325,6 +325,12 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_hash_table_free(clients); } + /* Return now if we are shutting down */ + if (server->server_shutdown) { + silc_hash_table_free(channels); + return TRUE; + } + /* We must now re-generate the channel key for all channels that had this server's client(s) on the channel. As they left the channel we must re-generate the channel key. */ diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index 0eef766e..5123bf07 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -1811,6 +1811,31 @@ silc_server_config_find_router_conn(SilcServer server, char *host, int port) return serv; } +/* Find backup router connection by host (name or ip) */ + +SilcServerConfigRouter * +silc_server_config_find_backup_conn(SilcServer server, char *host) +{ + SilcServerConfig config = server->config; + SilcServerConfigRouter *serv = NULL; + + if (!host) + return NULL; + + if (!config->routers) + return NULL; + + for (serv = config->routers; serv; serv = serv->next) { + if (!serv->backup_router) + continue; + if (!silc_string_compare(serv->host, host)) + continue; + break; + } + + return serv; +} + /* Returns TRUE if configuration for a router connection that we are initiating exists. */ diff --git a/apps/silcd/serverconfig.h b/apps/silcd/serverconfig.h index fc6c1095..268b8699 100644 --- a/apps/silcd/serverconfig.h +++ b/apps/silcd/serverconfig.h @@ -220,6 +220,8 @@ SilcServerConfigServer * silc_server_config_find_server_conn(SilcServer server, char *host); SilcServerConfigRouter * silc_server_config_find_router_conn(SilcServer server, char *host, int port); +SilcServerConfigRouter * +silc_server_config_find_backup_conn(SilcServer server, char *host); bool silc_server_config_is_primary_route(SilcServer server); SilcServerConfigRouter * silc_server_config_get_primary_router(SilcServer server); -- 2.24.0