mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
lws_conmon: connection monitoring and stats generation
This provides a build option LWS_WITH_CONMON that lets user code recover detailed connection stats on client connections with the LCCSCF_CONMON flag. In addition to latencies for dns, socket connection, tls and first protocol response where possible, it also provides the user code an unfiltered list of DNS responses that the client received, and the peer it actually succeded to connect to.
This commit is contained in:
parent
67eed51fea
commit
06509e287d
16 changed files with 438 additions and 2 deletions
|
@ -278,6 +278,7 @@ option(LWS_WITH_FANALYZER "Enable gcc -fanalyzer if compiler supports" OFF)
|
|||
option(LWS_HTTP_HEADERS_ALL "Override header reduction optimization and include all like older lws versions" OFF)
|
||||
option(LWS_WITH_SUL_DEBUGGING "Enable zombie lws_sul checking on object deletion" OFF)
|
||||
option(LWS_WITH_PLUGINS_API "Build generic lws_plugins apis (see LWS_WITH_PLUGINS to also build protocol plugins)" OFF)
|
||||
option(LWS_WITH_CONMON "Collect introspectable connection latency stats on individual client connections" ON)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
option(LWS_WITH_NETLINK "Monitor Netlink for Routing Table changes" ON)
|
||||
|
|
36
READMEs/README.lws_conmon.md
Normal file
36
READMEs/README.lws_conmon.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
## `lws_conmon` apis
|
||||
|
||||
`LWS_WITH_CONMON` build option enables `lws_conmon` apis for user code... these add
|
||||
some staticistic and information to client connections that can use useful for devices
|
||||
to introspect how the connection to their servers is actually performing.
|
||||
|
||||
The public apis can be found in `libwebsockets/lws-conmon.h`.
|
||||
|
||||
A struct is provided that describes
|
||||
|
||||
- the peer sockaddr the wsi actually connected to, if any
|
||||
|
||||
- a deep copy of the aggregate DNS results (struct addrinfo list) that the
|
||||
client had access to for the peer
|
||||
|
||||
- the number of us dns lookup took
|
||||
|
||||
- the number of us the socket connection took
|
||||
|
||||
- the number of us the tls link establishment took
|
||||
|
||||
- the number of us from the transaction request to the first response, if
|
||||
the protocol has a transaction concept
|
||||
|
||||
Because the user code may want to hold on to the DNS list for longer than the
|
||||
life of the wsi that originated it, the `lws_conmon_wsi_take()` api allows
|
||||
the ownership of the allocated list to be transferred to the user code (as
|
||||
well as copying data out into the user's struct so it no longer has any
|
||||
dependency on wsi lifetime either). The DNS list copy in the struct must be
|
||||
released at some point by calling `lws_conmon_release()`, but that
|
||||
can be at any time afterwards.
|
||||
|
||||
The lws-minimal-http-client example shows how user code can use the apis, build
|
||||
lws with the `LWS_WITH_CONMON` cmake option and run with `--conmon` to get a
|
||||
dump of the collected information.
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
#cmakedefine LWS_WITH_SYS_ASYNC_DNS
|
||||
#cmakedefine LWS_WITH_BORINGSSL
|
||||
#cmakedefine LWS_WITH_CGI
|
||||
#cmakedefine LWS_WITH_SECURE_STREAMS_CPP
|
||||
#cmakedefine LWS_WITH_CONMON
|
||||
#cmakedefine LWS_WITH_CUSTOM_HEADERS
|
||||
#cmakedefine LWS_WITH_DEPRECATED_LWS_DLL
|
||||
#cmakedefine LWS_WITH_DETAILED_LATENCY
|
||||
|
@ -177,6 +177,7 @@
|
|||
#cmakedefine LWS_WITH_RANGES
|
||||
#cmakedefine LWS_WITH_RFC6724
|
||||
#cmakedefine LWS_WITH_SECURE_STREAMS
|
||||
#cmakedefine LWS_WITH_SECURE_STREAMS_CPP
|
||||
#cmakedefine LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM
|
||||
#cmakedefine LWS_WITH_SECURE_STREAMS_PROXY_API
|
||||
#cmakedefine LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY
|
||||
|
|
|
@ -585,6 +585,10 @@ struct lws;
|
|||
|
||||
#include <libwebsockets/lws-context-vhost.h>
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
#include <libwebsockets/lws-conmon.h>
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_MQTT)
|
||||
#include <libwebsockets/lws-mqtt.h>
|
||||
#endif
|
||||
|
|
|
@ -90,6 +90,9 @@ enum lws_client_connect_ssl_connection_flags {
|
|||
LCCSCF_IP_LOW_COST = (1 << 27),
|
||||
/**< set the "minimize monetary cost" bit on the IP packets of this
|
||||
* connection */
|
||||
LCCSCF_CONMON = (1 << 28),
|
||||
/**< If LWS_WITH_CONMON enabled for build, keeps a copy of the
|
||||
* getaddrinfo results so they can be queried subsequently */
|
||||
};
|
||||
|
||||
/** struct lws_client_connect_info - parameters to connect with when using
|
||||
|
|
98
include/libwebsockets/lws-conmon.h
Normal file
98
include/libwebsockets/lws-conmon.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup conmon Connection Latency information
|
||||
* ## Connection Latency information
|
||||
*
|
||||
* When LWS_WITH_CONMON is enabled at build, collects detailed statistics
|
||||
* about the client connection setup latency, available to the connection
|
||||
* itself
|
||||
*/
|
||||
///@{
|
||||
|
||||
/* enough for 4191us, or just over an hour */
|
||||
typedef uint32_t lws_conmon_interval_us_t;
|
||||
|
||||
/*
|
||||
* Connection latency information... note that not all wsi actually make
|
||||
* connections, for example h2 streams after the initial one will have 0
|
||||
* for everything except ciu_txn_resp.
|
||||
*/
|
||||
|
||||
struct lws_conmon {
|
||||
lws_sockaddr46 peer46;
|
||||
/**< The peer we actually connected to, if any. .peer46.sa4.sa_family
|
||||
* is either 0 if invalid, or the AF_ */
|
||||
|
||||
struct addrinfo *dns_results_copy;
|
||||
/**< NULL, or Allocated copy of dns results, owned by this object and
|
||||
* freed when object destroyed.
|
||||
* Only set if client flag LCCSCF_CONMON applied */
|
||||
|
||||
lws_conmon_interval_us_t ciu_dns;
|
||||
/**< 0, or if a socket connection, us taken to acquire this DNS response
|
||||
*
|
||||
*/
|
||||
lws_conmon_interval_us_t ciu_sockconn;
|
||||
/**< 0, or if connection-based, the us interval between the socket
|
||||
* connect() attempt that succeeded, and the connection setup */
|
||||
lws_conmon_interval_us_t ciu_tls;
|
||||
/**< 0 if no tls, or us taken to establish the tls tunnel */
|
||||
lws_conmon_interval_us_t ciu_txn_resp;
|
||||
/**< 0, or if the protocol supports transactions, the interval between
|
||||
* sending the transaction request and starting to receive the resp */
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_conmon_wsi_take() - create a connection latency object from client wsi
|
||||
*
|
||||
* \param context: lws wsi
|
||||
* \param dest: conmon struct to fill
|
||||
*
|
||||
* Copies wsi conmon data into the caller's struct. Passes ownership of
|
||||
* any allocations in the addrinfo list to the caller, lws will not delete that
|
||||
* any more on wsi close after this call. The caller must call
|
||||
* lws_conmon_release() on the struct to destroy any addrinfo in the struct
|
||||
* that is prepared by this eventually but it can defer it as long as it wants.
|
||||
*
|
||||
* Other than the addrinfo list, the contents of the returned object are
|
||||
* completely selfcontained and don't point outside of the object itself, ie,
|
||||
* everything else in there remains in scope while the object itself does.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_conmon_wsi_take(struct lws *wsi, struct lws_conmon *dest);
|
||||
|
||||
/**
|
||||
* lws_conmon_release() - free any allocations in the conmon struct
|
||||
*
|
||||
* \param conmon: pointer to conmon struct
|
||||
*
|
||||
* Destroys any allocations in the conmon struct so it can go out of scope.
|
||||
* It doesn't free \p dest itself, it's designed to clean out a struct that
|
||||
* is on the stack or embedded in another object.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_conmon_release(struct lws_conmon *conmon);
|
||||
|
||||
///@}
|
|
@ -70,6 +70,11 @@ if (LWS_WITH_CLIENT)
|
|||
core-net/client/connect4.c
|
||||
core-net/client/sort-dns.c
|
||||
)
|
||||
if (LWS_WITH_CONMON)
|
||||
list(APPEND SOURCES
|
||||
core-net/client/conmon.c
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_SOCKS5 AND NOT LWS_WITHOUT_CLIENT)
|
||||
|
|
151
lib/core-net/client/conmon.c
Normal file
151
lib/core-net/client/conmon.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2019 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Client Connection Latency and DNS reporting
|
||||
*/
|
||||
|
||||
/*
|
||||
* We want to allocate copies for and append DNS results that we don't already
|
||||
* have. We take this approach because a) we may be getting duplicated results
|
||||
* from multiple DNS servers, and b) we may be getting results stacatto over
|
||||
* time.
|
||||
*
|
||||
* We capture DNS results from either getaddrinfo or ASYNC_DNS the same here,
|
||||
* before they are sorted and filtered.
|
||||
*
|
||||
* Because this is relatively expensive, we only do it on client wsi that
|
||||
* explicitly indicated that they want it with the LCCSCF_CONMON flag.
|
||||
*/
|
||||
|
||||
#include <private-lib-core.h>
|
||||
|
||||
int
|
||||
lws_conmon_append_copy_new_dns_results(struct lws *wsi,
|
||||
const struct addrinfo *cai)
|
||||
{
|
||||
if (!(wsi->flags & LCCSCF_CONMON))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Let's go through the incoming guys, seeing if we already have them,
|
||||
* or if we want to take a copy
|
||||
*/
|
||||
|
||||
while (cai) {
|
||||
struct addrinfo *ai = wsi->conmon.dns_results_copy;
|
||||
char skip = 0;
|
||||
|
||||
/* do we already have this guy? */
|
||||
|
||||
while (ai) {
|
||||
|
||||
if (ai->ai_family != cai->ai_family &&
|
||||
ai->ai_addrlen != cai->ai_addrlen &&
|
||||
ai->ai_protocol != cai->ai_protocol &&
|
||||
ai->ai_socktype != cai->ai_socktype &&
|
||||
/* either ipv4 or v6 address must match */
|
||||
((ai->ai_family == AF_INET &&
|
||||
((struct sockaddr_in *)ai->ai_addr)->
|
||||
sin_addr.s_addr ==
|
||||
((struct sockaddr_in *)cai->ai_addr)->
|
||||
sin_addr.s_addr)
|
||||
#if defined(LWS_WITH_IPV6)
|
||||
||
|
||||
(ai->ai_family == AF_INET6 &&
|
||||
!memcmp(((struct sockaddr_in6 *)ai->ai_addr)->
|
||||
sin6_addr.s6_addr,
|
||||
((struct sockaddr_in6 *)cai->ai_addr)->
|
||||
sin6_addr.s6_addr, 16))
|
||||
#endif
|
||||
)) {
|
||||
/* yes, we already got a copy then */
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ai = ai->ai_next;
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
/*
|
||||
* No we don't already have a copy of this one, let's
|
||||
* allocate and append it then
|
||||
*/
|
||||
size_t al = sizeof(struct addrinfo) + cai->ai_addrlen;
|
||||
size_t cl = cai->ai_canonname ?
|
||||
strlen(cai->ai_canonname) + 1 : 0;
|
||||
|
||||
ai = lws_malloc(al + cl, __func__);
|
||||
if (!ai) {
|
||||
lwsl_warn("%s: OOM\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
*ai = *cai;
|
||||
ai->ai_addr = (struct sockaddr *)&ai[1];
|
||||
memcpy(ai->ai_addr, cai->ai_addr, cai->ai_addrlen);
|
||||
|
||||
if (cl) {
|
||||
ai->ai_canonname = ((char *)ai->ai_addr) +
|
||||
cai->ai_addrlen;
|
||||
memcpy(ai->ai_canonname, cai->ai_canonname, cl + 1);
|
||||
}
|
||||
ai->ai_next = wsi->conmon.dns_results_copy;
|
||||
wsi->conmon.dns_results_copy = ai;
|
||||
}
|
||||
|
||||
cai = cai->ai_next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
lws_conmon_addrinfo_destroy(struct addrinfo *ai)
|
||||
{
|
||||
while (ai) {
|
||||
struct addrinfo *ai1 = ai->ai_next;
|
||||
|
||||
lws_free(ai);
|
||||
ai = ai1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lws_conmon_wsi_take(struct lws *wsi, struct lws_conmon *dest)
|
||||
{
|
||||
memcpy(dest, &wsi->conmon, sizeof(*dest));
|
||||
dest->peer46 = wsi->sa46_peer;
|
||||
|
||||
/* wsi no longer has to free it... */
|
||||
wsi->conmon.dns_results_copy = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
lws_conmon_release(struct lws_conmon *conmon)
|
||||
{
|
||||
if (!conmon)
|
||||
return;
|
||||
|
||||
lws_conmon_addrinfo_destroy(conmon->dns_results_copy);
|
||||
conmon->dns_results_copy = NULL;
|
||||
}
|
|
@ -57,9 +57,18 @@ lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
|
|||
hints.ai_family = PF_UNSPEC;
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon_datum = lws_now_usecs();
|
||||
#endif
|
||||
|
||||
wsi->dns_reachability = 0;
|
||||
n = getaddrinfo(ads, NULL, &hints, result);
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon.ciu_dns = (lws_conmon_interval_us_t)
|
||||
(lws_now_usecs() - wsi->conmon_datum);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Which EAI_* are available and the meanings are highly platform-
|
||||
* dependent, even different linux distros differ.
|
||||
|
|
|
@ -164,6 +164,12 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
|
|||
|
||||
if (result) {
|
||||
lws_sul_cancel(&wsi->sul_connect_timeout);
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
/* append a copy from before the sorting */
|
||||
lws_conmon_append_copy_new_dns_results(wsi, result);
|
||||
#endif
|
||||
|
||||
lws_sort_dns(wsi, result);
|
||||
#if defined(LWS_WITH_SYS_ASYNC_DNS)
|
||||
lws_async_dns_freeaddrinfo(&result);
|
||||
|
@ -433,6 +439,11 @@ ads_known:
|
|||
wsi->socket_is_permanently_unusable = 0;
|
||||
m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, (unsigned int)n);
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon_datum = lws_now_usecs();
|
||||
wsi->conmon.ciu_sockconn = 0;
|
||||
#endif
|
||||
|
||||
if (m == -1) {
|
||||
/*
|
||||
* Since we're nonblocking, connect not having completed is not
|
||||
|
@ -458,6 +469,11 @@ ads_known:
|
|||
* The connect() failed immediately...
|
||||
*/
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon.ciu_sockconn = (lws_conmon_interval_us_t)
|
||||
(lws_now_usecs() - wsi->conmon_datum);
|
||||
#endif
|
||||
|
||||
lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO);
|
||||
|
||||
#if defined(_DEBUG)
|
||||
|
@ -471,6 +487,8 @@ ads_known:
|
|||
sizeof(nads));
|
||||
lwsl_info("%s: Connect failed: %s port %d\n", __func__,
|
||||
nads, port);
|
||||
|
||||
wsi->sa46_peer.sa4.sin_family = 0;
|
||||
#if defined(LWS_WITH_UNIX_SOCK)
|
||||
}
|
||||
#endif
|
||||
|
@ -514,6 +532,11 @@ conn_good:
|
|||
* The connection has happened
|
||||
*/
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon.ciu_sockconn = (lws_conmon_interval_us_t)
|
||||
(lws_now_usecs() - wsi->conmon_datum);
|
||||
#endif
|
||||
|
||||
#if !defined(LWS_PLAT_OPTEE)
|
||||
{
|
||||
socklen_t salen = sizeof(wsi->sa46_local);
|
||||
|
|
|
@ -46,6 +46,19 @@ __lws_reset_wsi(struct lws *wsi)
|
|||
|
||||
lws_free_set_NULL(wsi->cli_hostname_copy);
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
|
||||
if (wsi->conmon.dns_results_copy) {
|
||||
lws_conmon_addrinfo_destroy(wsi->conmon.dns_results_copy);
|
||||
wsi->conmon.dns_results_copy = NULL;
|
||||
}
|
||||
|
||||
wsi->conmon.ciu_dns =
|
||||
wsi->conmon.ciu_sockconn =
|
||||
wsi->conmon.ciu_tls =
|
||||
wsi->conmon.ciu_txn_resp = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if we have wsi in our transaction queue, if we are closing we
|
||||
* must go through and close all those first
|
||||
|
|
|
@ -718,7 +718,12 @@ struct lws {
|
|||
#if defined(LWS_WITH_CLIENT)
|
||||
struct client_info_stash *stash;
|
||||
char *cli_hostname_copy;
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
struct lws_conmon conmon;
|
||||
lws_usec_t conmon_datum;
|
||||
#endif
|
||||
#endif /* WITH_CLIENT */
|
||||
void *user_space;
|
||||
void *opaque_parent_data;
|
||||
|
||||
|
@ -945,6 +950,13 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status, const char *caller)
|
|||
void
|
||||
__lws_free_wsi(struct lws *wsi);
|
||||
|
||||
void
|
||||
lws_conmon_addrinfo_destroy(struct addrinfo *ai);
|
||||
|
||||
int
|
||||
lws_conmon_append_copy_new_dns_results(struct lws *wsi,
|
||||
const struct addrinfo *cai);
|
||||
|
||||
#if LWS_MAX_SMP > 1
|
||||
|
||||
static LWS_INLINE void
|
||||
|
|
|
@ -1463,7 +1463,17 @@ lws_h2_parse_end_of_frame(struct lws *wsi)
|
|||
h2n->swsi->client_h2_alpn = 1;
|
||||
#if defined(LWS_WITH_CLIENT)
|
||||
h2n->swsi->flags = wsi->flags;
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
/* sid1 needs to represent the connection experience
|
||||
* ... we take over responsibility for the DNS list
|
||||
* copy as well
|
||||
*/
|
||||
h2n->swsi->conmon = wsi->conmon;
|
||||
h2n->swsi->conmon_datum = wsi->conmon_datum;
|
||||
h2n->swsi->sa46_peer = wsi->sa46_peer;
|
||||
wsi->conmon.dns_results_copy = NULL;
|
||||
#endif
|
||||
#endif /* CLIENT */
|
||||
|
||||
h2n->swsi->a.protocol = wsi->a.protocol;
|
||||
if (h2n->swsi->user_space &&
|
||||
|
|
|
@ -570,6 +570,11 @@ lws_client_interpret_server_handshake(struct lws *wsi)
|
|||
|
||||
lws_free_set_NULL(wsi->stash);
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon.ciu_txn_resp = (lws_conmon_interval_us_t)
|
||||
(lws_now_usecs() - wsi->conmon_datum);
|
||||
#endif
|
||||
|
||||
ah = wsi->http.ah;
|
||||
if (!wsi->do_ws) {
|
||||
/* we are being an http client...
|
||||
|
@ -1206,6 +1211,9 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt)
|
|||
lws_callback_on_writable(wsi);
|
||||
|
||||
lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mt_http_txn);
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon_datum = lws_now_usecs();
|
||||
#endif
|
||||
|
||||
// puts(pkt);
|
||||
|
||||
|
|
|
@ -35,6 +35,10 @@ lws_ssl_client_connect1(struct lws *wsi, char *errbuf, size_t len)
|
|||
return -1;
|
||||
case LWS_SSL_CAPABLE_DONE:
|
||||
lws_metrics_caliper_report(wsi->cal_conn, METRES_GO);
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon.ciu_tls = (lws_conmon_interval_us_t)
|
||||
(lws_now_usecs() - wsi->conmon_datum);
|
||||
#endif
|
||||
return 1; /* connected */
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
|
||||
lws_callback_on_writable(wsi);
|
||||
|
@ -80,6 +84,10 @@ lws_ssl_client_connect2(struct lws *wsi, char *errbuf, size_t len)
|
|||
}
|
||||
|
||||
lws_metrics_caliper_report(wsi->cal_conn, METRES_GO);
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon.ciu_tls = (lws_conmon_interval_us_t)
|
||||
(lws_now_usecs() - wsi->conmon_datum);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -194,6 +202,9 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1)
|
|||
|
||||
lws_metrics_caliper_report(wsi->cal_conn, METRES_GO);
|
||||
lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mt_conn_tls);
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
wsi->conmon_datum = lws_now_usecs();
|
||||
#endif
|
||||
|
||||
n = lws_ssl_client_connect1(wsi, (char *)wsi->a.context->pt[(int)wsi->tsi].serv_buf,
|
||||
wsi->a.context->pt_serv_buf_size);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
static int interrupted, bad = 1, status;
|
||||
static int interrupted, bad = 1, status, conmon;
|
||||
#if defined(LWS_WITH_HTTP2)
|
||||
static int long_poll;
|
||||
#endif
|
||||
|
@ -28,6 +28,40 @@ static const lws_retry_bo_t retry = {
|
|||
.secs_since_valid_hangup = 10,
|
||||
};
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
void
|
||||
dump_conmon_data(struct lws *wsi)
|
||||
{
|
||||
const struct addrinfo *ai;
|
||||
struct lws_conmon cm;
|
||||
char ads[48];
|
||||
|
||||
lws_conmon_wsi_take(wsi, &cm);
|
||||
|
||||
lws_sa46_write_numeric_address(&cm.peer46, ads, sizeof(ads));
|
||||
lwsl_notice("%s: peer %s, dns: %uus, sockconn: %uus, tls: %uus, txn_resp: %uus\n",
|
||||
__func__, ads,
|
||||
(unsigned int)cm.ciu_dns,
|
||||
(unsigned int)cm.ciu_sockconn,
|
||||
(unsigned int)cm.ciu_tls,
|
||||
(unsigned int)cm.ciu_txn_resp);
|
||||
|
||||
ai = cm.dns_results_copy;
|
||||
while (ai) {
|
||||
lws_sa46_write_numeric_address((lws_sockaddr46 *)ai->ai_addr, ads, sizeof(ads));
|
||||
lwsl_notice("%s: DNS %s\n", __func__, ads);
|
||||
ai = ai->ai_next;
|
||||
}
|
||||
|
||||
/*
|
||||
* This destroys the DNS list in the lws_conmon that we took
|
||||
* responsibility for when we used lws_conmon_wsi_take()
|
||||
*/
|
||||
|
||||
lws_conmon_release(&cm);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
|
@ -39,6 +73,12 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
lwsl_err("CLIENT_CONNECTION_ERROR: %s\n",
|
||||
in ? (char *)in : "(null)");
|
||||
interrupted = 1;
|
||||
lws_cancel_service(lws_get_context(wsi));
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
if (conmon)
|
||||
dump_conmon_data(wsi);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
|
@ -128,6 +168,10 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
interrupted = 1;
|
||||
bad = status != 200;
|
||||
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
if (conmon)
|
||||
dump_conmon_data(wsi);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -234,6 +278,13 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link,
|
|||
i.manual_initial_tx_credit);
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_CONMON)
|
||||
if (lws_cmdline_option(a->argc, a->argv, "--conmon")) {
|
||||
i.ssl_connection |= LCCSCF_CONMON;
|
||||
conmon = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* the default validity check is 5m / 5m10s... -v = 3s / 10s */
|
||||
|
||||
if (lws_cmdline_option(a->argc, a->argv, "-v"))
|
||||
|
|
Loading…
Add table
Reference in a new issue