deletion on backup router.
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 <priikone@silcnet.org>
* Stop for a couple seconds after badkup router has become
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 &&
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);
}
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])
/* 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;
}
/* 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;
/* 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;
/* 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)
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))
/* 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;
/* 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;
/* 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)
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;
if (!channel) {
SILC_LOG_ERROR(("Received key for non-existent channel %s",
silc_id_render(id, SILC_ID_CHANNEL)));
+ assert(FALSE);
goto out;
}
}
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 */
/* 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);
/* 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);
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. */
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. */
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);