From: Jochen Eisinger Date: Fri, 13 Feb 2004 11:07:08 +0000 (+0000) Subject: Fri Feb 13 12:04:41 CET 2004 Jochen Eisinger X-Git-Tag: silc.server.0.9.17~30 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=cd5b6de3ece76e34874a51e597e13200011d48f7 Fri Feb 13 12:04:41 CET 2004 Jochen Eisinger * use asynchronous connect() to establish router connections. Fixes problem when the primary router goes down. Affected files silcd/server.c, silcd/server_backup.c --- diff --git a/CHANGES b/CHANGES index 0f505a0a..1d74cb0f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +Fri Feb 13 12:04:41 CET 2004 Jochen Eisinger + + * 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 * Surrogates not allowed in UTF-8 strings, updated decoder. diff --git a/apps/silcd/server.c b/apps/silcd/server.c index d8fd164c..4606461b 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -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 diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index 16d0d7e7..2032717e 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -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