diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/README.md b/minimal-examples/ws-client/minimal-ws-client-ping/README.md index 014e67a23..4cfc0ec66 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/README.md +++ b/minimal-examples/ws-client/minimal-ws-client-ping/README.md @@ -2,7 +2,8 @@ This connects to libwebsockets.org using the lws-mirror-protocol. -It then sends a ws PING every 5s and records any PONG coming back. +It sets a validity regime of testing validity with PING every 3s and failing +if it didn't get the PONG back within 10s. ## build @@ -14,12 +15,10 @@ It then sends a ws PING every 5s and records any PONG coming back. Option|Meaning ---|--- --d|Set logging verbosity +-d|Set logging verbosity (you want 1039 to see the validity ping / pong) --server|Use a specific server instead of libwebsockets.org, eg `--server localhost`. Implies LCCSCF_ALLOW_SELFSIGNED --port|Use a specific port instead of 443, eg `--port 7681` --z|Send zero-length pings for testing --protocol|Use a specific ws subprotocol rather than lws-mirror-protocol, eg, `--protocol myprotocol` --v|Connection validity use 3s / 10s instead of default 5m / 5m10s ## usage @@ -28,17 +27,91 @@ Just run it, wait for the connect and then there will be PINGs sent at 5s intervals. ``` - $ ./lws-minimal-ws-client-ping -[2018/05/09 16:55:03:1160] USER: LWS minimal ws client PING -[2018/05/09 16:55:03:1379] NOTICE: Creating Vhost 'default' (serving disabled), 1 protocols, IPv6 off -[2018/05/09 16:55:03:1715] NOTICE: client loaded CA for verification ./libwebsockets.org.cer -[2018/05/09 16:55:03:1717] NOTICE: created client ssl context for default -[2018/05/09 16:55:04:8332] USER: callback_minimal_broker: established -[2018/05/09 16:55:09:8389] USER: Sending PING 10... -[2018/05/09 16:55:10:1491] USER: LWS_CALLBACK_CLIENT_RECEIVE_PONG -[2018/05/09 16:55:10:1494] NOTICE: -[2018/05/09 16:55:10:1514] NOTICE: 0000: 70 69 6E 67 20 62 6F 64 79 21 ping body! -[2018/05/09 16:55:10:1515] NOTICE: + $ ./lws-minimal-ws-client-ping -d1039 +[2020/03/18 13:13:47:1114] U: LWS minimal ws client PING +[2020/03/18 13:13:47:1503] I: Initial logging level 1039 +[2020/03/18 13:13:47:1507] I: Libwebsockets version: 4.0.99 v4.0.0-20-gc6165f868 +[2020/03/18 13:13:47:1508] I: IPV6 not compiled in +[2020/03/18 13:13:47:1512] I: LWS_DEF_HEADER_LEN : 4096 +[2020/03/18 13:13:47:1514] I: LWS_MAX_SMP : 1 +[2020/03/18 13:13:47:1519] I: sizeof (*info) : 720 +[2020/03/18 13:13:47:1520] I: SYSTEM_RANDOM_FILEPATH: '/dev/urandom' +[2020/03/18 13:13:47:1522] I: HTTP2 support : available +[2020/03/18 13:13:47:1552] N: lws_create_context: using ss proxy bind '(null)', port 0, ads '(null)' +[2020/03/18 13:13:47:1557] I: context created +[2020/03/18 13:13:47:1575] I: Using event loop: poll +[2020/03/18 13:13:47:1583] I: Default ALPN advertisment: h2,http/1.1 +[2020/03/18 13:13:47:1585] I: default timeout (secs): 20 +[2020/03/18 13:13:47:1614] I: Threads: 1 each 5 fds +[2020/03/18 13:13:47:1623] I: mem: context: 8152 B (4056 ctx + (1 thr x 4096)) +[2020/03/18 13:13:47:1625] I: mem: http hdr size: (4096 + 976), max count 5 +[2020/03/18 13:13:47:1629] I: mem: pollfd map: 40 B +[2020/03/18 13:13:47:1633] I: mem: platform fd map: 40 B +[2020/03/18 13:13:47:1692] I: Compiled with OpenSSL support +[2020/03/18 13:13:47:1695] I: Doing SSL library init +[2020/03/18 13:13:47:3103] I: canonical_hostname = constance +[2020/03/18 13:13:47:3140] I: Creating Vhost 'default' (serving disabled), 4 protocols, IPv6 off +[2020/03/18 13:13:47:4072] I: lws_tls_client_create_vhost_context: vh default: created new client ctx 0 +[2020/03/18 13:13:47:7468] I: created client ssl context for default +[2020/03/18 13:13:47:7482] I: Creating Vhost 'default' (serving disabled), 4 protocols, IPv6 off +[2020/03/18 13:13:47:7490] I: lws_tls_client_create_vhost_context: vh default: reusing client ctx 0: use 2 +[2020/03/18 13:13:47:7491] I: created client ssl context for default +[2020/03/18 13:13:47:7494] I: mem: per-conn: 792 bytes + protocol rx buf +[2020/03/18 13:13:47:7497] I: lws_plat_drop_app_privileges: not changing group +[2020/03/18 13:13:47:7499] I: lws_plat_drop_app_privileges: not changing user +[2020/03/18 13:13:47:7512] I: lws_cancel_service +[2020/03/18 13:13:47:7568] I: lws_state_notify_protocol_init: LWS_SYSTATE_CPD_PRE_TIME +[2020/03/18 13:13:47:7577] N: lws_ss_create: unknown stream type captive_portal_detect +[2020/03/18 13:13:47:7580] I: lws_ss_sys_cpd: Create stream failed (policy?) +[2020/03/18 13:13:47:7582] I: lws_state_notify_protocol_init: LWS_SYSTATE_CPD_PRE_TIME +[2020/03/18 13:13:47:7582] N: lws_ss_create: unknown stream type captive_portal_detect +[2020/03/18 13:13:47:7583] I: lws_ss_sys_cpd: Create stream failed (policy?) +[2020/03/18 13:13:47:7585] I: lws_state_notify_protocol_init: doing protocol init on POLICY_VALID +[2020/03/18 13:13:47:7588] I: lws_protocol_init +[2020/03/18 13:13:47:7623] I: lws_state_transition_steps: CONTEXT_CREATED -> OPERATIONAL +[2020/03/18 13:13:47:7628] N: connect_cb: connecting +[2020/03/18 13:13:47:7656] I: lws_client_connect_via_info: role binding to h1 +[2020/03/18 13:13:47:7662] I: lws_client_connect_via_info: protocol binding to lws-ping-test +[2020/03/18 13:13:47:7699] I: lws_client_connect_via_info: wsi 0x5669090: h1 lws-ping-test entry +[2020/03/18 13:13:47:7720] I: lws_header_table_attach: wsi 0x5669090: ah (nil) (tsi 0, count = 0) in +[2020/03/18 13:13:47:7729] I: _lws_create_ah: created ah 0x5669620 (size 4096): pool length 1 +[2020/03/18 13:13:47:7735] I: lws_header_table_attach: did attach wsi 0x5669090: ah 0x5669620: count 1 (on exit) +[2020/03/18 13:13:47:7780] I: lws_client_connect_2_dnsreq: 0x5669090: lookup libwebsockets.org:443 +[2020/03/18 13:13:47:8784] I: lws_getaddrinfo46: getaddrinfo 'libwebsockets.org' says 0 +[2020/03/18 13:13:47:8804] I: lws_client_connect_3_connect: libwebsockets.org ipv4 46.105.127.147 +[2020/03/18 13:13:47:9176] I: lws_client_connect_3_connect: getsockopt check: conn OK +[2020/03/18 13:13:47:9179] I: lws_client_connect_3_connect: Connection started 0x5682cc0 +[2020/03/18 13:13:47:9197] I: lws_client_connect_4_established: wsi 0x5669090: h1 lws-ping-test client created own conn (raw 0) vh defaultm st 0x202 +[2020/03/18 13:13:47:9418] I: h1 client conn using alpn list 'http/1.1' +[2020/03/18 13:13:48:4523] I: lws_role_call_alpn_negotiated: 'http/1.1' +[2020/03/18 13:13:48:4531] I: client connect OK +[2020/03/18 13:13:48:4543] I: lws_openssl_describe_cipher: wsi 0x5669090: TLS_AES_256_GCM_SHA384, TLS_AES_256_GCM_SHA384, 256 bits, TLSv1.3 +[2020/03/18 13:13:48:4717] I: lws_client_socket_service: HANDSHAKE2: 0x5669090: sending headers (wsistate 0x10000204), w sock 5 +[2020/03/18 13:13:48:4992] I: lws_buflist_aware_read: wsi 0x5669090: lws_client_socket_service: ssl_capable_read -4 +[2020/03/18 13:13:48:5005] I: lws_buflist_aware_read: wsi 0x5669090: lws_client_socket_service: ssl_capable_read 174 +[2020/03/18 13:13:48:5166] I: __lws_header_table_detach: wsi 0x5669090: ah 0x5669620 (tsi=0, count = 1) +[2020/03/18 13:13:48:5171] I: __lws_header_table_detach: nobody usable waiting +[2020/03/18 13:13:48:5175] I: _lws_destroy_ah: freed ah 0x5669620 : pool length 0 +[2020/03/18 13:13:48:5180] I: __lws_header_table_detach: wsi 0x5669090: ah 0x5669620 (tsi=0, count = 0) +[2020/03/18 13:13:48:5197] I: _lws_validity_confirmed_role: wsi 0x5669090: setting validity timer 3s (hup 0) +[2020/03/18 13:13:48:5208] U: callback_minimal_broker: established +[2020/03/18 13:13:51:5218] I: lws_validity_cb: wsi 0x5669090: scheduling validity check +[2020/03/18 13:13:51:5325] I: rops_handle_POLLOUT_ws: issuing ping on wsi 0x5669090: ws lws-ping-test h2: 0 +[2020/03/18 13:13:51:5504] I: lws_issue_raw: ssl_capable_write (6) says 6 +[2020/03/18 13:13:51:5809] I: lws_ws_client_rx_sm: client 0x5669090 received pong +[2020/03/18 13:13:51:5819] I: _lws_validity_confirmed_role: wsi 0x5669090: setting validity timer 3s (hup 0) +[2020/03/18 13:13:51:5831] I: Client doing pong callback +[2020/03/18 13:13:54:5821] I: lws_validity_cb: wsi 0x5669090: scheduling validity check +[2020/03/18 13:13:54:5825] I: rops_handle_POLLOUT_ws: issuing ping on wsi 0x5669090: ws lws-ping-test h2: 0 +[2020/03/18 13:13:54:5833] I: lws_issue_raw: ssl_capable_write (6) says 6 +[2020/03/18 13:13:54:6258] I: lws_ws_client_rx_sm: client 0x5669090 received pong +[2020/03/18 13:13:54:6261] I: _lws_validity_confirmed_role: wsi 0x5669090: setting validity timer 3s (hup 0) +[2020/03/18 13:13:54:6263] I: Client doing pong callback +[2020/03/18 13:13:57:6263] I: lws_validity_cb: wsi 0x5669090: scheduling validity check +[2020/03/18 13:13:57:6267] I: rops_handle_POLLOUT_ws: issuing ping on wsi 0x5669090: ws lws-ping-test h2: 0 +[2020/03/18 13:13:57:6275] I: lws_issue_raw: ssl_capable_write (6) says 6 +[2020/03/18 13:13:58:0034] I: lws_ws_client_rx_sm: client 0x5669090 received pong + ... ``` diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c b/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c index 63279ff2e..a8589f0ef 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c +++ b/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c @@ -1,13 +1,14 @@ /* * lws-minimal-ws-client-ping * - * Written in 2010-2019 by Andy Green + * Written in 2010-2020 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. * - * This demonstrates a ws client that sends pings from time to time and - * shows when it receives the PONG + * This demonstrates keeping a ws connection validated by the lws validity + * timer stuff without having to do anything in the code. Use debug logging + * -d1039 to see lws doing the pings / pongs in the background. */ #include @@ -17,24 +18,22 @@ static struct lws_context *context; static struct lws *client_wsi; -static int interrupted, zero_length_ping, port = 443, quick_pings, no_user_ping, - ssl_connection = LCCSCF_USE_SSL; +static int interrupted, port = 443, ssl_connection = LCCSCF_USE_SSL; static const char *server_address = "libwebsockets.org", *pro = "lws-mirror-protocol"; - -struct pss { - int send_a_ping; -}; +static lws_sorted_usec_list_t sul; static const lws_retry_bo_t retry = { .secs_since_valid_ping = 3, .secs_since_valid_hangup = 10, }; -static int -connect_client(void) +static void +connect_cb(lws_sorted_usec_list_t *_sul) { struct lws_client_connect_info i; + lwsl_notice("%s: connecting\n", __func__); + memset(&i, 0, sizeof(i)); i.context = context; @@ -45,95 +44,30 @@ connect_client(void) i.origin = i.address; i.ssl_connection = ssl_connection; i.protocol = pro; + i.alpn = "h2;http/1.1"; i.local_protocol_name = "lws-ping-test"; i.pwsi = &client_wsi; - if (quick_pings) - i.retry_and_idle_policy = &retry; + i.retry_and_idle_policy = &retry; - return !lws_client_connect_via_info(&i); + if (!lws_client_connect_via_info(&i)) + lws_sul_schedule(context, 0, _sul, connect_cb, 5 * LWS_USEC_PER_SEC); } static int -callback_minimal_broker(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) +callback_minimal_pingtest(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { - struct pss *pss = (struct pss *)user; - int n; switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: - goto try; - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); - client_wsi = NULL; - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), LWS_CALLBACK_USER, 1); + lws_sul_schedule(context, 0, &sul, connect_cb, 5 * LWS_USEC_PER_SEC); break; - /* --- client callbacks --- */ - case LWS_CALLBACK_CLIENT_ESTABLISHED: lwsl_user("%s: established\n", __func__); - lws_set_timer_usecs(wsi, 5 * LWS_USEC_PER_SEC); - break; - - case LWS_CALLBACK_CLIENT_WRITEABLE: - if (pss->send_a_ping) { - uint8_t ping[LWS_PRE + 125]; - int m; - - pss->send_a_ping = 0; - n = 0; - if (!zero_length_ping) - n = lws_snprintf((char *)ping + LWS_PRE, 125, - "ping body!"); - - lwsl_user("Sending PING %d...\n", n); - - m = lws_write(wsi, ping + LWS_PRE, n, LWS_WRITE_PING); - if (m < n) { - lwsl_err("sending ping failed: %d\n", m); - - return -1; - } - - lws_callback_on_writable(wsi); - } - break; - - case LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL: - client_wsi = NULL; - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); - break; - - case LWS_CALLBACK_CLIENT_RECEIVE_PONG: - lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE_PONG\n"); - lwsl_hexdump_notice(in, len); - break; - - case LWS_CALLBACK_TIMER: - if (no_user_ping) - break; - /* we want to send a ws PING every few seconds */ - pss->send_a_ping = 1; - lws_callback_on_writable(wsi); - lws_set_timer_usecs(wsi, 10 * LWS_USEC_PER_SEC); - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); -try: - if (connect_client()) - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); break; default: @@ -146,8 +80,8 @@ try: static const struct lws_protocols protocols[] = { { "lws-ping-test", - callback_minimal_broker, - sizeof(struct pss), + callback_minimal_pingtest, + 0, 0, }, { NULL, NULL, 0, 0 } @@ -191,12 +125,6 @@ int main(int argc, const char **argv) info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; #endif - if (lws_cmdline_option(argc, argv, "-z")) - zero_length_ping = 1; - - if (lws_cmdline_option(argc, argv, "-n")) - no_user_ping = 1; - if ((p = lws_cmdline_option(argc, argv, "--protocol"))) pro = p; @@ -209,18 +137,6 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "--port"))) port = atoi(p); - /* the default validity check is 5m / 5m10s... -v = 5s / 10s */ - - if (lws_cmdline_option(argc, argv, "-v")) - quick_pings = 1; - - /* - * 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 - * have to use the default allocations for fd tables up to ulimit -n. - * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we - * will use. - */ info.fd_limit_per_thread = 1 + 1 + 1; context = lws_create_context(&info); @@ -229,6 +145,8 @@ int main(int argc, const char **argv) return 1; } + lws_sul_schedule(context, 0, &sul, connect_cb, 100); + while (n >= 0 && !interrupted) n = lws_service(context, 0);