Fixed notify sending to backup routers, and fixed channel
authorPekka Riikonen <priikone@silcnet.org>
Thu, 27 Jun 2002 12:21:58 +0000 (12:21 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 27 Jun 2002 12:21:58 +0000 (12:21 +0000)
deletion on backup router.

CHANGES
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/server_internal.h
apps/silcd/server_util.c
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h

diff --git a/CHANGES b/CHANGES
index e559274feb257cd3de0403ab63a17a510c590709..09d6d39aea3e73cd71d1508329eedfdba1fb52d1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,21 @@ Thu Jun 27 11:27:07 CEST 2002 Pekka Riikonen <priikone@silcnet.org>
          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
index 33d1bce0a40d521b22fd95580175c5801084ad22..ed8ad2f02233f60144601d03e16a4a5f08571f07 100644 (file)
@@ -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 &&
index 14895b2ec9e6af20a4b3a7bdc21a9ea92263953b..65637c159c79e73438fa85cf8e658e8f0a7173df 100644 (file)
@@ -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);
 }
index 1f6a778910c0aeb76782a77a747ad55dfe68a2f5..cc772361c46533c3036059ae928ac873495bdbfd 100644 (file)
@@ -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;
       }
     }
index f7e70f46f103db00a4663f7c216ccf18272068cb..74babfaae7ac02fd5a3f81d20baa364c26536ed5 100644 (file)
@@ -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 */
index d0157e3a5736740679016c5d45476dcfdb3862bf..183819318d3a9a52fc295315aa3dc57517731586 100644 (file)
@@ -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. */
index 0eef766e6c867c94a2cd5bd4de8cd93a01daf62c..5123bf0722a7ea0cc2e75284fdc1a6787c5324c9 100644 (file)
@@ -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. */
 
index fc6c109592c84e13229e7db28f69e0d2245a9385..268b8699f1afbc71c920d7fd0c1f219efa6f812e 100644 (file)
@@ -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);