Fri Feb 13 12:04:41 CET 2004 Jochen Eisinger <jochen@penguin-breeder.org>
authorJochen Eisinger <coffee@silcnet.org>
Fri, 13 Feb 2004 11:07:08 +0000 (11:07 +0000)
committerJochen Eisinger <coffee@silcnet.org>
Fri, 13 Feb 2004 11:07:08 +0000 (11:07 +0000)
* use asynchronous connect() to establish router connections.
  Fixes problem when the primary router goes down.  Affected files
  silcd/server.c, silcd/server_backup.c

CHANGES
apps/silcd/server.c
apps/silcd/server_backup.c

diff --git a/CHANGES b/CHANGES
index 0f505a0ad4fc8f527daed279937acb37e8ca1514..1d74cb0fd150a3af4ca8b37ae1e6d602b482a757 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+Fri Feb 13 12:04:41 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * use asynchronous connect() to establish router connections.
+         Fixes problem when the primary router goes down.  Affected files
+         silcd/server.c, silcd/server_backup.c
+
 Tue Feb  3 23:25:17 EET 2004  Pekka Riikonen <priikone@silcnet.org>
 
        * Surrogates not allowed in UTF-8 strings, updated decoder.
index d8fd164cae5d1438f421b331ebcbb610efb009b4..4606461b97af0fe6d0b477ee1c9efb7044ffbb7c 100644 (file)
@@ -962,6 +962,45 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
+/* callback for async connection to remote router */
+
+SILC_TASK_CALLBACK(silc_server_connect_router); /* forward decl */
+
+SILC_TASK_CALLBACK(silc_server_connection_established)
+{
+  SilcServer server = app_context;
+  SilcServerConnection sconn = (SilcServerConnection)context;
+  int sock = fd;
+  int opt = EINVAL, optlen = sizeof(opt);
+
+  silc_schedule_task_del_by_fd(server->schedule, sock);
+  silc_schedule_unset_listen_fd(server->schedule, sock);
+
+  if (silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen) || 
+      (opt != 0)) {
+    SILC_LOG_ERROR(("Could not connect to router %s:%d: %s",
+                   sconn->remote_host, sconn->remote_port,
+                   strerror(opt)));
+    if (!sconn->no_reconnect)
+      silc_schedule_task_add(server->schedule, 0,
+                            silc_server_connect_to_router_retry,
+                            context, 0, 1, SILC_TASK_TIMEOUT,
+                            SILC_TASK_PRI_NORMAL);
+    else {
+      silc_server_config_unref(&sconn->conn);
+      silc_free(sconn->remote_host);
+      silc_free(sconn->backup_replace_ip);
+      silc_free(sconn);
+    }
+    return;
+  }
+
+  SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
+                 sconn->remote_port));
+
+  /* Continue with key exchange protocol */
+  silc_server_start_key_exchange(server, sconn, sock);
+}
 /* Generic routine to use connect to a router. */
 
 SILC_TASK_CALLBACK(silc_server_connect_router)
@@ -998,7 +1037,7 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
   silc_server_config_ref(&sconn->conn, server->config, (void *)rconn);
 
   /* Connect to remote host */
-  sock = silc_net_create_connection(
+  sock = silc_net_create_connection_async(
                 (!server->config->server_info->primary ? NULL :
                  server->config->server_info->primary->server_ip),
                 sconn->remote_port, sconn->remote_host);
@@ -1019,8 +1058,13 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
     return;
   }
 
-  /* Continue with key exchange protocol */
-  silc_server_start_key_exchange(server, sconn, sock);
+  /* wait for the connection to be established */
+  silc_schedule_task_add(server->schedule, sock,
+                        silc_server_connection_established,
+                        context, 0, 0, SILC_TASK_FD,
+                        SILC_TASK_PRI_NORMAL);
+  silc_schedule_set_listen_fd(server->schedule, sock,
+                             SILC_TASK_WRITE, FALSE);
 }
 
 /* This function connects to our primary router or if we are a router this
index 16d0d7e76150955f8967381e38aab8ce0f8cbe03..2032717e70ddd664a7b10849812db2916d4d2d37 100644 (file)
@@ -780,6 +780,48 @@ void silc_server_backup_resume_router(SilcServer server,
   }
 }
 
+/* callback for async connection to remote router */
+
+SILC_TASK_CALLBACK(silc_server_backup_connect_to_router); /* forward decl */
+
+SILC_TASK_CALLBACK(silc_server_backup_connection_established)
+{
+  SilcServer server = app_context;
+  SilcServerConnection sconn = (SilcServerConnection)context;
+  int sock = fd;
+  int opt = EINVAL, optlen = sizeof(opt);
+
+  silc_schedule_task_del_by_fd(server->schedule, sock);
+  silc_schedule_unset_listen_fd(server->schedule, sock);
+
+  if (silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen) || 
+      (opt != 0)) {
+    SILC_LOG_DEBUG(("Could not connect to router %s:%d: %s", sconn->remote_host,
+                   sconn->remote_port, strerror(opt)));
+                   
+    if (server->server_type == SILC_SERVER) {
+      sconn->retry_count++;
+      if (sconn->retry_count > 3) {
+       silc_free(sconn->remote_host);
+       silc_free(sconn);
+       return;
+      }
+    }
+    silc_schedule_task_add(server->schedule, 0,
+                          silc_server_backup_connect_to_router,
+                          context, 10, 0, SILC_TASK_TIMEOUT,
+                          SILC_TASK_PRI_NORMAL);
+    return;
+  }
+
+  SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
+                 sconn->remote_port));
+
+  /* Continue with key exchange protocol */
+  silc_server_start_key_exchange(server, sconn, sock);
+}
+
+
 /* Timeout task callback to connect to remote router */
 
 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
@@ -795,8 +837,8 @@ 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;
-  sock = silc_net_create_connection(server_ip, sconn->remote_port,
-                                   sconn->remote_host);
+  sock = silc_net_create_connection_async(server_ip, sconn->remote_port,
+                                         sconn->remote_host);
   if (sock < 0) {
     if (server->server_type == SILC_SERVER) {
       sconn->retry_count++;
@@ -813,8 +855,13 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
     return;
   }
 
-  /* Continue with key exchange protocol */
-  silc_server_start_key_exchange(server, sconn, sock);
+  /* wait for the connection to be established */
+  silc_schedule_task_add(server->schedule, sock,
+                        silc_server_backup_connection_established,
+                        context, 0, 0, SILC_TASK_FD,
+                        SILC_TASK_PRI_NORMAL);
+  silc_schedule_set_listen_fd(server->schedule, sock,
+                             SILC_TASK_WRITE, FALSE);
 }
 
 /* Constantly tries to reconnect to a primary router indicated by the