Completed the backup router support for standalone routers.
[silc.git] / apps / silcd / server_backup.c
index 1383e6ceb201dc2e78409ed015965a1cb0e0236a..6c77135d7e02dc3c77ca05c22361867cb9b1ab31 100644 (file)
@@ -22,6 +22,9 @@
 #include "server_internal.h"
 
 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
+static void silc_server_backup_connect_primary(SilcServer server,
+                                              SilcServerEntry server_entry,
+                                              void *context);
 
 /* Backup router */
 typedef struct {
@@ -180,7 +183,7 @@ void silc_server_backup_replaced_add(SilcServer server,
     server->backup->replaced_count = 1;
   }
 
-  SILC_LOG_DEBUG(("Replacing router %s with %s backup",
+  SILC_LOG_DEBUG(("Replacing router %s with %s",
                  silc_id_render(server_id, SILC_ID_SERVER),
                  server_entry->server_name));
 
@@ -336,12 +339,8 @@ void silc_server_backup_send(SilcServer server,
 
   for (i = 0; i < server->backup->servers_count; i++) {
     backup = server->backup->servers[i].server;
-    if (!backup)
-      continue;
-
-    if (sender == backup)
+    if (!backup || sender == backup)
       continue;
-
     if (local && server->backup->servers[i].local == FALSE)
       continue;
     if (server->backup->servers[i].server == server->id_entry)
@@ -382,12 +381,8 @@ void silc_server_backup_send_dest(SilcServer server,
 
   for (i = 0; i < server->backup->servers_count; i++) {
     backup = server->backup->servers[i].server;
-    if (!backup)
-      continue;
-
-    if (sender == backup)
+    if (!backup || sender == backup)
       continue;
-
     if (local && server->backup->servers[i].local == FALSE)
       continue;
     if (server->backup->servers[i].server == server->id_entry)
@@ -534,7 +529,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
 
   /* Connect to remote host */
   server_ip = server->config->server_info->primary == NULL ? NULL :
-               server->config->server_info->primary->server_ip;
+    server->config->server_info->primary->server_ip;
   sock = silc_net_create_connection(server_ip, sconn->remote_port,
                                    sconn->remote_host);
   if (sock < 0) {
@@ -566,6 +561,7 @@ void silc_server_backup_reconnect(SilcServer server,
   sconn->remote_port = port;
   sconn->callback = callback;
   sconn->callback_context = context;
+  sconn->no_reconnect = TRUE;
   silc_schedule_task_add(server->schedule, 0, 
                         silc_server_backup_connect_to_router,
                         sconn, 1, 0, SILC_TASK_TIMEOUT,
@@ -600,8 +596,21 @@ void silc_server_backup_connected(SilcServer server,
                                  void *context)
 {
   SilcServerBackupProtocolContext proto_ctx;
-  SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
+  SilcSocketConnection sock;
+
+  if (!server_entry) {
+    /* Try again */
+    SilcServerConfigRouter *primary;
+    primary = silc_server_config_get_primary_router(server);
+    if (primary)
+      silc_server_backup_reconnect(server,
+                                  primary->host, primary->port,
+                                  silc_server_backup_connected,
+                                  context);
+    return;
+  }
 
+  sock = (SilcSocketConnection)server_entry->connection;
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->server = server;
   proto_ctx->sock = sock;
@@ -627,12 +636,27 @@ static void silc_server_backup_connect_primary(SilcServer server,
                                               void *context)
 {
   SilcSocketConnection backup_router = (SilcSocketConnection)context;
-  SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
-  SilcIDListData idata = (SilcIDListData)server_entry;
-  SilcServerBackupProtocolContext ctx = 
-    (SilcServerBackupProtocolContext)backup_router->protocol->context;
+  SilcServerBackupProtocolContext ctx;
+  SilcSocketConnection sock;
+  SilcIDListData idata;
   SilcBuffer buffer;
 
+  if (!server_entry) {
+    /* Try again */
+    SilcServerConfigRouter *primary;
+    primary = silc_server_config_get_primary_router(server);
+    if (primary)
+      silc_server_backup_reconnect(server,
+                                  primary->host, primary->port,
+                                  silc_server_backup_connect_primary,
+                                  context);
+    return;
+  }
+
+  ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context;
+  sock = (SilcSocketConnection)server_entry->connection;
+  idata = (SilcIDListData)server_entry;
+
   SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
 
   /* Send the CONNECTED packet back to the backup router. */
@@ -806,10 +830,15 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
       silc_buffer_free(packet);
 
-      /* 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);
+      /* If we are not standalone and our primary is not the one we've
+        talking to now, then announce our information to it since we
+        haven't done that yet.  Standalone backup router announces
+        these during connecting to the primary. */
+      if (!server->standalone && SILC_PRIMARY_ROUTE(server) != ctx->sock) {
+       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 {
@@ -926,10 +955,11 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
       /* Switch announced informations to our primary router of using the
         backup router. */
+      silc_server_local_servers_toggle_enabled(server, TRUE);
       silc_server_update_servers_by_server(server, ctx->sock->user_data, 
-                                          server->router, TRUE);
+                                          server->router);
       silc_server_update_clients_by_server(server, ctx->sock->user_data,
-                                          server->router, TRUE, FALSE);
+                                          server->router, TRUE);
       if (server->server_type == SILC_SERVER)
        silc_server_update_channels_by_server(server, ctx->sock->user_data, 
                                              server->router);
@@ -1050,38 +1080,34 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
          /* We have new primary router now */
          server->id_entry->router = router;
          server->router = router;
-         server->router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
-
          SILC_LOG_INFO(("Switching back to primary router %s",
                         server->router->server_name));
-
-         /* We cannot talk to backup router connection anymore, it's
-            enabled again if primary goes down. */
-         backup_router->data.status |= SILC_IDLIST_STATUS_DISABLED;
        } else {
          /* We are connected to new primary and now continue using it */
-         router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
          SILC_LOG_INFO(("Resuming the use of primary router %s",
                         router->server_name));
        }
 
        /* Update the client entries of the backup router to the new 
           router */
-       silc_server_update_servers_by_server(server, backup_router, router,
-                                            FALSE);
-       silc_server_update_clients_by_server(server, NULL, router, 
-                                            FALSE, FALSE);
+       silc_server_local_servers_toggle_enabled(server, FALSE);
+       router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+       silc_server_update_servers_by_server(server, backup_router, router);
+       silc_server_update_clients_by_server(server, NULL, router, 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);
 
        /* Announce all of our information to the router. */
        if (server->server_type == SILC_ROUTER)
-         silc_server_announce_servers(server, FALSE, 0, router->connection);
+         silc_server_announce_servers(server, FALSE, ctx->start,
+                                      router->connection);
 
        /* Announce our clients and channels to the router */
-       silc_server_announce_clients(server, 0, router->connection);
-       silc_server_announce_channels(server, 0, router->connection);
+       silc_server_announce_clients(server, ctx->start,
+                                    router->connection);
+       silc_server_announce_channels(server, ctx->start,
+                                     router->connection);
       }
 
       /* Send notify about primary router going down to local operators */