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:
parent
c97b68272c
commit
36ec353dac
13 changed files with 82 additions and 31 deletions
|
@ -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" */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue