1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

client: allow setting overall connect timeout from vh init

Add a member to the vh init struct allowing control of the overall
connection wait introduced in an earlier patch.  Set it to 20s
by default.


The timeout_secs member controls the individual DNS result
connect timeout and is reduced to 5s by default.
This commit is contained in:
Andy Green 2020-05-26 17:05:39 +01:00
parent c97b68272c
commit 36ec353dac
13 changed files with 82 additions and 31 deletions

View file

@ -402,6 +402,10 @@ struct lws_context_creation_info {
* library are protected from hanging forever by timeouts. If
* nonzero, this member lets you set the timeout used in seconds.
* Otherwise a default timeout is used. */
unsigned int connect_timeout_secs;
/**< VHOST: client connections have this long to find a working server
* from the DNS results, or the whole connection times out. If zero,
* a default timeout is used */
const char *ecdh_curve;
/**< VHOST: if NULL, defaults to initializing server with
* "prime256v1" */

View file

@ -590,6 +590,7 @@ struct lws_vhost {
int ka_interval;
int keepalive_timeout;
int timeout_secs_ah_idle;
int connect_timeout_secs;
int count_bound_wsi;

View file

@ -512,6 +512,12 @@ lws_create_vhost(struct lws_context *context,
vh->iface = info->iface;
#if !defined(LWS_PLAT_FREERTOS) && !defined(OPTEE_TA) && !defined(WIN32)
vh->bind_iface = info->bind_iface;
#endif
#if defined(LWS_WITH_CLIENT)
if (info->connect_timeout_secs)
vh->connect_timeout_secs = info->connect_timeout_secs;
else
vh->connect_timeout_secs = 20;
#endif
/* apply the context default lws_retry */

View file

@ -548,7 +548,7 @@ lws_create_context(const struct lws_context_creation_info *info)
if (info->timeout_secs)
context->timeout_secs = info->timeout_secs;
else
context->timeout_secs = AWAITING_TIMEOUT;
context->timeout_secs = 5;
context->ws_ping_pong_interval = info->ws_ping_pong_interval;

View file

@ -82,9 +82,6 @@
#ifndef SPEC_LATEST_SUPPORTED
#define SPEC_LATEST_SUPPORTED 13
#endif
#ifndef AWAITING_TIMEOUT
#define AWAITING_TIMEOUT 30
#endif
#ifndef CIPHERS_LIST_STRING
#define CIPHERS_LIST_STRING "DEFAULT"
#endif

View file

@ -73,7 +73,7 @@ delete_from_fd(struct lws_context *context, lws_sockfd_type fd)
return 0;
}
lwsl_err("Failed to find fd %d requested for "
lwsl_debug("Failed to find fd %d requested for "
"delete in hashtable\n", fd);
return 1;
}

View file

@ -194,13 +194,34 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
pfd->revents = (short)networkevents.lNetworkEvents;
err = networkevents.iErrorCode[FD_CONNECT_BIT];
if ((networkevents.lNetworkEvents & FD_CONNECT) && wsi_from_fd(context, pfd->fd) && !wsi_from_fd(context, pfd->fd)->udp) {
lwsl_debug("%s: FD_CONNECT: %p\n", __func__, wsi_from_fd(context, pfd->fd));
pfd->revents &= ~LWS_POLLOUT;
if (err && err != LWS_EALREADY &&
err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK &&
err != WSAEINVAL) {
lwsl_debug("Unable to connect errno=%d\n", err);
if ((networkevents.lNetworkEvents & FD_CONNECT) &&
err && err != LWS_EALREADY &&
err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK &&
err != WSAEINVAL) {
lwsl_debug("Unable to connect errno=%d\n", err);
pfd->revents |= LWS_POLLHUP;
/*
* the connection has definitively failed... but
* do we have more DNS entries to try?
*/
if (wsi_from_fd(context, pfd->fd)->dns_results_next) {
lws_sul_schedule(context, 0, &wsi_from_fd(context, pfd->fd)->
sul_connect_timeout,
lws_client_conn_wait_timeout, 1);
continue;
} else
pfd->revents |= LWS_POLLHUP;
} else
if (wsi_from_fd(context, pfd->fd)) {
if (wsi_from_fd(context, pfd->fd)->udp)
pfd->revents |= LWS_POLLHUP;
else
lws_client_connect_3_connect(wsi_from_fd(context, pfd->fd),
NULL, NULL, LWS_CONNECT_COMPLETION_GOOD,
NULL);
}
}
if (pfd->revents & LWS_POLLOUT) {

View file

@ -280,7 +280,7 @@ send_hs:
* provoke service to issue the CONNECT directly.
*/
lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
AWAITING_TIMEOUT);
wsi->context->timeout_secs);
assert(lws_socket_is_valid(wsi->desc.sockfd));
@ -356,6 +356,10 @@ lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul)
* connection before giving up on it and retrying.
*/
#if defined(WIN32)
wsi->dns_results_next = wsi->dns_results_next->ai_next;
#endif
lwsl_info("%s: connect wait timeout has fired\n", __func__);
lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL);
}
@ -380,6 +384,9 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
char ni[48];
int m;
if (n == LWS_CONNECT_COMPLETION_GOOD)
goto conn_good;
#if defined(LWS_WITH_IPV6) && defined(__ANDROID__)
ipv6only = 0;
#endif
@ -393,7 +400,6 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue))
return wsi;
#if !defined(WIN32)
/*
* We can check using getsockopt if our connect actually completed.
* Posix connect() allows nonblocking to redo the connect to
@ -406,22 +412,31 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
socklen_t sl = sizeof(int);
int e = 0;
if (!result && !wsi->sul_connect_timeout.list.owner)
if (!result && /* no dns results... */
!wsi->sul_connect_timeout.list.owner /* no ongoing connect timeout */)
goto connect_to;
#if defined(WIN32)
if (!connect(wsi->desc.sockfd, NULL, 0)) {
goto conn_good;
} else {
if (!LWS_ERRNO || LWS_ERRNO == WSAEINVAL ||
LWS_ERRNO == WSAEWOULDBLOCK || LWS_ERRNO == WSAEALREADY) {
lwsl_info("%s: errno %d\n", __func__, errno);
return NULL;
}
lwsl_info("%s: connect check take as FAILED\n", __func__);
}
#else
/*
* this resets SO_ERROR after reading it. If there's an error
* condition the connect definitively failed.
*/
if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
#if defined(WIN32)
(char *)
#endif
&e, &sl)) {
if (!e) {
lwsl_info("%s: getsockopt check: conn OK\n",
__func__);
lwsl_debug("%s: getsockopt check: conn OK errno %d\n",
__func__, errno);
goto conn_good;
}
@ -429,12 +444,12 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
lwsl_debug("%s: getsockopt fd %d says err %d\n", __func__,
wsi->desc.sockfd, e);
}
#endif
lwsl_debug("%s: getsockopt check: conn fail: errno %d\n",
__func__, LWS_ERRNO);
goto try_next_result_fds;
}
#endif
#if defined(LWS_WITH_UNIX_SOCK)
if (ads && *ads == '+') {
@ -551,7 +566,8 @@ next_result:
ni[0] = '\0';
lws_write_numeric_address(sa46.sa6.sin6_addr.s6_addr,
16, ni, sizeof(ni));
lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__, ads, ni);
lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__,
ads ? ads : "(null)", ni);
break;
}
#endif
@ -564,7 +580,7 @@ next_result:
n = sizeof(struct sockaddr_in);
lws_write_numeric_address((uint8_t *)&sa46.sa4.sin_addr.s_addr,
4, ni, sizeof(ni));
lwsl_info("%s: %s ipv4 %s\n", __func__, ads, ni);
lwsl_info("%s: %s ipv4 %s\n", __func__, ads ? ads : "(null)", ni);
break;
case AF_INET6:
#if defined(LWS_WITH_IPV6)
@ -581,7 +597,7 @@ next_result:
sa46.sa6.sin6_port = htons(port);
lws_write_numeric_address((uint8_t *)&sa46.sa6.sin6_addr,
16, ni, sizeof(ni));
lwsl_info("%s: %s ipv6 %s\n", __func__, ads, ni);
lwsl_info("%s: %s ipv6 %s\n", __func__, ads ? ads : "(null)", ni);
#else
goto try_next_result; /* ipv4 only can't use this */
#endif
@ -653,7 +669,7 @@ ads_known:
wsi->protocol = &wsi->vhost->protocols[0];
lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
wsi->context->timeout_secs);
wsi->vhost->connect_timeout_secs);
iface = lws_wsi_client_stash_item(wsi, CIS_IFACE,
_WSI_TOKEN_CLIENT_IFACE);
@ -685,9 +701,6 @@ ads_known:
wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
#endif
if (!result && !wsi->sul_connect_timeout.list.owner)
goto connect_to;
m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, n);
if (m == -1) {
int errno_copy = LWS_ERRNO;
@ -719,8 +732,9 @@ ads_known:
#endif
/*
* Let's set a specialized timeout for the connect completion,
* it uses wsi->sul_connect_timeout just for this purpose
* Let's set a specialized timeout for this connect attempt
* completion, it uses wsi->sul_connect_timeout just for this
* purpose
*/
lws_sul_schedule(wsi->context, 0, &wsi->sul_connect_timeout,
@ -802,7 +816,6 @@ oom4:
return NULL;
connect_to:
/*
* It looks like the sul_connect_timeout fired

View file

@ -341,6 +341,8 @@ enum {
LWS_UPG_RET_BAIL
};
#define LWS_CONNECT_COMPLETION_GOOD (-99)
int
lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot);

View file

@ -259,6 +259,8 @@ int main(int argc, const char **argv)
info.protocols = protocols;
info.user = &args;
info.register_notifier_list = na;
info.timeout_secs = 10;
info.connect_timeout_secs = 30;
/*
* since we know this lws context is only ever going to be used with

View file

@ -162,6 +162,8 @@ int main(int argc, const char **argv)
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
info.protocols = protocols;
info.pt_serv_buf_size = 8192;
info.timeout_secs = 10;
info.connect_timeout_secs = 30;
/*
* since we know this lws context is only ever going to be used with
* one client wsis / fds / sockets at a time, let lws know it doesn't

View file

@ -282,6 +282,7 @@ int main(int argc, const char **argv)
info.protocols = protocols;
info.user = &args;
info.register_notifier_list = na;
info.connect_timeout_secs = 30;
/*
* since we know this lws context is only ever going to be used with

View file

@ -99,6 +99,8 @@ int main(int argc, const char **argv)
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
info.protocols = protocols;
info.timeout_secs = 10;
info.connect_timeout_secs = 30;
#if defined(LWS_WITH_MBEDTLS)
/*
* OpenSSL uses the system trust store. mbedTLS has to be told which