2 * lws-minimal-ws-client-ping
4 * Written in 2010-2019 by Andy Green <andy@warmcat.com>
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
9 * This demonstrates a ws client that sends pings from time to time and
10 * shows when it receives the PONG
13 #include <libwebsockets.h>
18 static struct lws_context *context;
19 static struct lws *client_wsi;
20 static int interrupted, zero_length_ping, port = 443,
21 ssl_connection = LCCSCF_USE_SSL;
22 static const char *server_address = "libwebsockets.org", *pro = "lws-mirror-protocol";
31 struct lws_client_connect_info i;
33 memset(&i, 0, sizeof(i));
37 i.address = server_address;
41 i.ssl_connection = ssl_connection;
43 i.local_protocol_name = "lws-ping-test";
46 return !lws_client_connect_via_info(&i);
50 callback_minimal_broker(struct lws *wsi, enum lws_callback_reasons reason,
51 void *user, void *in, size_t len)
53 struct pss *pss = (struct pss *)user;
58 case LWS_CALLBACK_PROTOCOL_INIT:
61 case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
62 lwsl_err("CLIENT_CONNECTION_ERROR: %s\n",
63 in ? (char *)in : "(null)");
65 lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
66 lws_get_protocol(wsi), LWS_CALLBACK_USER, 1);
69 /* --- client callbacks --- */
71 case LWS_CALLBACK_CLIENT_ESTABLISHED:
72 lwsl_user("%s: established\n", __func__);
73 lws_set_timer_usecs(wsi, 5 * LWS_USEC_PER_SEC);
76 case LWS_CALLBACK_CLIENT_WRITEABLE:
77 if (pss->send_a_ping) {
78 uint8_t ping[LWS_PRE + 125];
83 if (!zero_length_ping)
84 n = lws_snprintf((char *)ping + LWS_PRE, 125,
87 lwsl_user("Sending PING %d...\n", n);
89 m = lws_write(wsi, ping + LWS_PRE, n, LWS_WRITE_PING);
91 lwsl_err("sending ping failed: %d\n", m);
96 lws_callback_on_writable(wsi);
100 case LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL:
102 lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
103 lws_get_protocol(wsi),
104 LWS_CALLBACK_USER, 1);
107 case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
108 lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE_PONG\n");
109 lwsl_hexdump_notice(in, len);
112 case LWS_CALLBACK_TIMER:
113 /* we want to send a ws PING every few seconds */
114 pss->send_a_ping = 1;
115 lws_callback_on_writable(wsi);
116 lws_set_timer_usecs(wsi, 5 * LWS_USEC_PER_SEC);
119 /* rate-limited client connect retries */
121 case LWS_CALLBACK_USER:
122 lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__);
124 if (connect_client())
125 lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
126 lws_get_protocol(wsi),
127 LWS_CALLBACK_USER, 1);
134 return lws_callback_http_dummy(wsi, reason, user, in, len);
137 static const struct lws_protocols protocols[] = {
140 callback_minimal_broker,
148 sigint_handler(int sig)
153 int main(int argc, const char **argv)
155 struct lws_context_creation_info info;
157 int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
158 /* for LLL_ verbosity above NOTICE to be built into lws,
159 * lws must have been configured and built with
160 * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
161 /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
162 /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
165 signal(SIGINT, sigint_handler);
167 if ((p = lws_cmdline_option(argc, argv, "-d")))
170 lws_set_log_level(logs, NULL);
171 lwsl_user("LWS minimal ws client PING\n");
173 memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
174 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
175 info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
176 info.protocols = protocols;
177 #if defined(LWS_WITH_MBEDTLS)
179 * OpenSSL uses the system trust store. mbedTLS has to be told which
180 * CA to trust explicitly.
182 info.client_ssl_ca_filepath = "./libwebsockets.org.cer";
185 if (lws_cmdline_option(argc, argv, "-z"))
186 zero_length_ping = 1;
188 if ((p = lws_cmdline_option(argc, argv, "--protocol")))
191 if ((p = lws_cmdline_option(argc, argv, "--server"))) {
194 ssl_connection |= LCCSCF_ALLOW_SELFSIGNED;
197 if ((p = lws_cmdline_option(argc, argv, "--port")))
201 * since we know this lws context is only ever going to be used with
202 * one client wsis / fds / sockets at a time, let lws know it doesn't
203 * have to use the default allocations for fd tables up to ulimit -n.
204 * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
207 info.fd_limit_per_thread = 1 + 1 + 1;
209 context = lws_create_context(&info);
211 lwsl_err("lws init failed\n");
215 while (n >= 0 && !interrupted)
216 n = lws_service(context, 0);
218 lws_context_destroy(context);
219 lwsl_user("Completed\n");