diff --git a/src/protocols/telnet/settings.c b/src/protocols/telnet/settings.c index ddffc8e6..4211c58e 100644 --- a/src/protocols/telnet/settings.c +++ b/src/protocols/telnet/settings.c @@ -37,6 +37,7 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = { "hostname", "port", + "timeout", "username", "username-regex", "password", @@ -81,6 +82,11 @@ enum TELNET_ARGS_IDX { */ IDX_PORT, + /** + * The number of seconds to wait for the remote server to respond. Optional. + */ + IDX_TIMEOUT, + /** * The name of the user to login as. Optional. */ @@ -429,6 +435,11 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user, guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_PORT, GUAC_TELNET_DEFAULT_PORT); + /* Read connection timeout */ + settings->timeout = + guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, + IDX_TIMEOUT, GUAC_TELNET_DEFAULT_TIMEOUT); + /* Read typescript path */ settings->typescript_path = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, diff --git a/src/protocols/telnet/settings.h b/src/protocols/telnet/settings.h index 3c5ba8b9..02de1cb3 100644 --- a/src/protocols/telnet/settings.h +++ b/src/protocols/telnet/settings.h @@ -33,6 +33,12 @@ */ #define GUAC_TELNET_DEFAULT_PORT "23" +/** + * The default number of seconds to wait for a successful connection before + * timing out. + */ +#define GUAC_TELNET_DEFAULT_TIMEOUT 10 + /** * The filename to use for the typescript, if not specified. */ @@ -72,6 +78,11 @@ typedef struct guac_telnet_settings { */ char* port; + /** + * The number of seconds to wait for a connection before timing out. + */ + int timeout; + /** * The name of the user to login as, if any. If no username is specified, * this will be NULL. diff --git a/src/protocols/telnet/telnet.c b/src/protocols/telnet/telnet.c index 3a4c5049..5874859a 100644 --- a/src/protocols/telnet/telnet.c +++ b/src/protocols/telnet/telnet.c @@ -424,9 +424,25 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) { NI_NUMERICHOST | NI_NUMERICSERV))) guac_client_log(client, GUAC_LOG_DEBUG, "Unable to resolve host: %s", gai_strerror(retval)); - /* Connect */ - if (connect(fd, current_address->ai_addr, - current_address->ai_addrlen) == 0) { + fd_set fdset; + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + + struct timeval timeout_tv; + timeout_tv.tv_sec = settings->timeout; + timeout_tv.tv_usec = 0; + + connect(fd, current_address->ai_addr, current_address->ai_addrlen); + + retval = select(fd + 1, NULL, &fdset, NULL, &timeout_tv); + + if (retval == 0) { + guac_client_log(client, GUAC_LOG_ERROR, "Timeout connecting to " + "host %s, port %s", connected_address, connected_port); + continue; + } + + else if (retval > 0) { guac_client_log(client, GUAC_LOG_DEBUG, "Successfully connected to " "host %s, port %s", connected_address, connected_port);