+ silc_protocol_execute(protocol, server->schedule, 0, 0);
+}
+
+/* Timeout callback that will be called to retry connecting to remote
+ router. This is used by both normal and router server. This will wait
+ before retrying the connecting. The timeout is generated by exponential
+ backoff algorithm. */
+
+SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
+{
+ SilcServerConnection sconn = (SilcServerConnection)context;
+ SilcServer server = sconn->server;
+
+ SILC_LOG_INFO(("Retrying connecting to a router"));
+
+ /* Calculate next timeout */
+ if (sconn->retry_count >= 1) {
+ sconn->retry_timeout = sconn->retry_timeout * SILC_SERVER_RETRY_MULTIPLIER;
+ if (sconn->retry_timeout > SILC_SERVER_RETRY_INTERVAL_MAX)
+ sconn->retry_timeout = SILC_SERVER_RETRY_INTERVAL_MAX;
+ } else {
+ sconn->retry_timeout = server->params->retry_interval_min;
+ }
+ sconn->retry_count++;
+ sconn->retry_timeout = sconn->retry_timeout +
+ silc_rng_get_rn32(server->rng) % SILC_SERVER_RETRY_RANDOMIZER;
+
+ /* If we've reached max retry count, give up. */
+ if (sconn->retry_count > server->params->retry_count &&
+ server->params->retry_keep_trying == FALSE) {
+ SILC_LOG_ERROR(("Could not connect to router, giving up"));
+ silc_free(sconn->remote_host);
+ silc_free(sconn);
+ return;
+ }
+
+ /* Wait one before retrying */
+ silc_schedule_task_add(server->schedule, fd, silc_server_connect_router,
+ context, sconn->retry_timeout,
+ server->params->retry_interval_min_usec,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+}
+
+/* Generic routine to use connect to a router. */
+
+SILC_TASK_CALLBACK(silc_server_connect_router)
+{
+ SilcServerConnection sconn = (SilcServerConnection)context;
+ SilcServer server = sconn->server;
+ int sock;
+
+ SILC_LOG_INFO(("Connecting to the %s %s on port %d",
+ (sconn->backup ? "backup router" : "router"),
+ sconn->remote_host, sconn->remote_port));
+
+ server->router_connect = time(0);
+
+ /* Connect to remote host */
+ sock = silc_net_create_connection(server->config->server_info->server_ip,
+ sconn->remote_port,
+ sconn->remote_host);
+ if (sock < 0) {
+ SILC_LOG_ERROR(("Could not connect to router %s:%d",
+ sconn->remote_host, sconn->remote_port));
+ if (!sconn->no_reconnect)
+ silc_schedule_task_add(server->schedule, fd,
+ silc_server_connect_to_router_retry,
+ context, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ return;
+ }
+
+ /* Continue with key exchange protocol */
+ silc_server_start_key_exchange(server, sconn, sock);