1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets-test-client - libwebsockets test implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Written in 2010-2019 by Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * This file is made available under the Creative Commons CC0 1.0
7*1c60b9acSAndroid Build Coastguard Worker * Universal Public Domain Dedication.
8*1c60b9acSAndroid Build Coastguard Worker *
9*1c60b9acSAndroid Build Coastguard Worker * The person who associated a work with this deed has dedicated
10*1c60b9acSAndroid Build Coastguard Worker * the work to the public domain by waiving all of his or her rights
11*1c60b9acSAndroid Build Coastguard Worker * to the work worldwide under copyright law, including all related
12*1c60b9acSAndroid Build Coastguard Worker * and neighboring rights, to the extent allowed by law. You can copy,
13*1c60b9acSAndroid Build Coastguard Worker * modify, distribute and perform the work, even for commercial purposes,
14*1c60b9acSAndroid Build Coastguard Worker * all without asking permission.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * The test apps are intended to be adapted for use in your code, which
17*1c60b9acSAndroid Build Coastguard Worker * may be proprietary. So unlike the library itself, they are licensed
18*1c60b9acSAndroid Build Coastguard Worker * Public Domain.
19*1c60b9acSAndroid Build Coastguard Worker */
20*1c60b9acSAndroid Build Coastguard Worker
21*1c60b9acSAndroid Build Coastguard Worker #include "lws_config.h"
22*1c60b9acSAndroid Build Coastguard Worker
23*1c60b9acSAndroid Build Coastguard Worker #include <stdio.h>
24*1c60b9acSAndroid Build Coastguard Worker #include <stdlib.h>
25*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32)
26*1c60b9acSAndroid Build Coastguard Worker #include <getopt.h>
27*1c60b9acSAndroid Build Coastguard Worker #endif
28*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
29*1c60b9acSAndroid Build Coastguard Worker #include <signal.h>
30*1c60b9acSAndroid Build Coastguard Worker
31*1c60b9acSAndroid Build Coastguard Worker #ifdef _WIN32
32*1c60b9acSAndroid Build Coastguard Worker #define random rand
33*1c60b9acSAndroid Build Coastguard Worker #include "gettimeofday.h"
34*1c60b9acSAndroid Build Coastguard Worker #else
35*1c60b9acSAndroid Build Coastguard Worker #include <syslog.h>
36*1c60b9acSAndroid Build Coastguard Worker #include <sys/time.h>
37*1c60b9acSAndroid Build Coastguard Worker #include <unistd.h>
38*1c60b9acSAndroid Build Coastguard Worker #endif
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker struct lws_poly_gen {
43*1c60b9acSAndroid Build Coastguard Worker uint32_t cyc[2];
44*1c60b9acSAndroid Build Coastguard Worker };
45*1c60b9acSAndroid Build Coastguard Worker
46*1c60b9acSAndroid Build Coastguard Worker #define block_size (3 * 4096)
47*1c60b9acSAndroid Build Coastguard Worker
48*1c60b9acSAndroid Build Coastguard Worker static int deny_deflate, longlived, mirror_lifetime, test_post, once;
49*1c60b9acSAndroid Build Coastguard Worker static struct lws *wsi_dumb, *wsi_mirror;
50*1c60b9acSAndroid Build Coastguard Worker static struct lws *wsi_multi[3];
51*1c60b9acSAndroid Build Coastguard Worker static volatile int force_exit;
52*1c60b9acSAndroid Build Coastguard Worker static unsigned int opts, rl_multi[3];
53*1c60b9acSAndroid Build Coastguard Worker static int flag_no_mirror_traffic, justmirror, flag_echo;
54*1c60b9acSAndroid Build Coastguard Worker static uint32_t count_blocks = 1024, txb, rxb, rx_count, errs;
55*1c60b9acSAndroid Build Coastguard Worker static struct lws_poly_gen tx = { { 0xabcde, 0x23456789 } },
56*1c60b9acSAndroid Build Coastguard Worker rx = { { 0xabcde, 0x23456789 } }
57*1c60b9acSAndroid Build Coastguard Worker ;
58*1c60b9acSAndroid Build Coastguard Worker
59*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
60*1c60b9acSAndroid Build Coastguard Worker char crl_path[1024] = "";
61*1c60b9acSAndroid Build Coastguard Worker #endif
62*1c60b9acSAndroid Build Coastguard Worker
63*1c60b9acSAndroid Build Coastguard Worker /*
64*1c60b9acSAndroid Build Coastguard Worker * This demo shows how to connect multiple websockets simultaneously to a
65*1c60b9acSAndroid Build Coastguard Worker * websocket server (there is no restriction on their having to be the same
66*1c60b9acSAndroid Build Coastguard Worker * server just it simplifies the demo).
67*1c60b9acSAndroid Build Coastguard Worker *
68*1c60b9acSAndroid Build Coastguard Worker * dumb-increment-protocol: we connect to the server and print the number
69*1c60b9acSAndroid Build Coastguard Worker * we are given
70*1c60b9acSAndroid Build Coastguard Worker *
71*1c60b9acSAndroid Build Coastguard Worker * lws-mirror-protocol: draws random circles, which are mirrored on to every
72*1c60b9acSAndroid Build Coastguard Worker * client (see them being drawn in every browser
73*1c60b9acSAndroid Build Coastguard Worker * session also using the test server)
74*1c60b9acSAndroid Build Coastguard Worker */
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard Worker enum demo_protocols {
77*1c60b9acSAndroid Build Coastguard Worker
78*1c60b9acSAndroid Build Coastguard Worker PROTOCOL_DUMB_INCREMENT,
79*1c60b9acSAndroid Build Coastguard Worker PROTOCOL_LWS_MIRROR,
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker /* always last */
82*1c60b9acSAndroid Build Coastguard Worker DEMO_PROTOCOL_COUNT
83*1c60b9acSAndroid Build Coastguard Worker };
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker static uint8_t
lws_poly_rand(struct lws_poly_gen * p)86*1c60b9acSAndroid Build Coastguard Worker lws_poly_rand(struct lws_poly_gen *p)
87*1c60b9acSAndroid Build Coastguard Worker {
88*1c60b9acSAndroid Build Coastguard Worker p->cyc[0] = (p->cyc[0] & 1) ? (p->cyc[0] >> 1) ^ 0xb4bcd35c :
89*1c60b9acSAndroid Build Coastguard Worker p->cyc[0] >> 1;
90*1c60b9acSAndroid Build Coastguard Worker p->cyc[0] = (p->cyc[0] & 1) ? (p->cyc[0] >> 1) ^ 0xb4bcd35c :
91*1c60b9acSAndroid Build Coastguard Worker p->cyc[0] >> 1;
92*1c60b9acSAndroid Build Coastguard Worker p->cyc[1] = (p->cyc[1] & 1) ? (p->cyc[1] >> 1) ^ 0x7a5bc2e3 :
93*1c60b9acSAndroid Build Coastguard Worker p->cyc[1] >> 1;
94*1c60b9acSAndroid Build Coastguard Worker
95*1c60b9acSAndroid Build Coastguard Worker return (uint8_t)(p->cyc[0] ^ p->cyc[1]);
96*1c60b9acSAndroid Build Coastguard Worker }
97*1c60b9acSAndroid Build Coastguard Worker
show_http_content(const char * p,size_t l)98*1c60b9acSAndroid Build Coastguard Worker static void show_http_content(const char *p, size_t l)
99*1c60b9acSAndroid Build Coastguard Worker {
100*1c60b9acSAndroid Build Coastguard Worker if (lwsl_visible(LLL_INFO)) {
101*1c60b9acSAndroid Build Coastguard Worker while (l--)
102*1c60b9acSAndroid Build Coastguard Worker if (*p < 0x7f)
103*1c60b9acSAndroid Build Coastguard Worker putchar(*p++);
104*1c60b9acSAndroid Build Coastguard Worker else
105*1c60b9acSAndroid Build Coastguard Worker putchar('.');
106*1c60b9acSAndroid Build Coastguard Worker }
107*1c60b9acSAndroid Build Coastguard Worker }
108*1c60b9acSAndroid Build Coastguard Worker
109*1c60b9acSAndroid Build Coastguard Worker
110*1c60b9acSAndroid Build Coastguard Worker /*
111*1c60b9acSAndroid Build Coastguard Worker * dumb_increment protocol
112*1c60b9acSAndroid Build Coastguard Worker *
113*1c60b9acSAndroid Build Coastguard Worker * since this also happens to be protocols[0], some callbacks that are not
114*1c60b9acSAndroid Build Coastguard Worker * bound to a specific protocol also turn up here.
115*1c60b9acSAndroid Build Coastguard Worker */
116*1c60b9acSAndroid Build Coastguard Worker
117*1c60b9acSAndroid Build Coastguard Worker static int
callback_dumb_increment(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)118*1c60b9acSAndroid Build Coastguard Worker callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
119*1c60b9acSAndroid Build Coastguard Worker void *user, void *in, size_t len)
120*1c60b9acSAndroid Build Coastguard Worker {
121*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
122*1c60b9acSAndroid Build Coastguard Worker union lws_tls_cert_info_results ci;
123*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_CTIME_R) && !defined(LWS_WITH_NO_LOGS)
124*1c60b9acSAndroid Build Coastguard Worker char date[32];
125*1c60b9acSAndroid Build Coastguard Worker #endif
126*1c60b9acSAndroid Build Coastguard Worker #endif
127*1c60b9acSAndroid Build Coastguard Worker const char *which = "http";
128*1c60b9acSAndroid Build Coastguard Worker char which_wsi[10], buf[50 + LWS_PRE];
129*1c60b9acSAndroid Build Coastguard Worker int n;
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker switch (reason) {
132*1c60b9acSAndroid Build Coastguard Worker
133*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_ESTABLISHED:
134*1c60b9acSAndroid Build Coastguard Worker lwsl_info("dumb: LWS_CALLBACK_CLIENT_ESTABLISHED\n");
135*1c60b9acSAndroid Build Coastguard Worker break;
136*1c60b9acSAndroid Build Coastguard Worker
137*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLOSED:
138*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("dumb: LWS_CALLBACK_CLOSED\n");
139*1c60b9acSAndroid Build Coastguard Worker wsi_dumb = NULL;
140*1c60b9acSAndroid Build Coastguard Worker break;
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_RECEIVE:
143*1c60b9acSAndroid Build Coastguard Worker ((char *)in)[len] = '\0';
144*1c60b9acSAndroid Build Coastguard Worker lwsl_info("rx %d '%s'\n", (int)len, (char *)in);
145*1c60b9acSAndroid Build Coastguard Worker break;
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker /* because we are protocols[0] ... */
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
150*1c60b9acSAndroid Build Coastguard Worker if (wsi == wsi_dumb) {
151*1c60b9acSAndroid Build Coastguard Worker which = "dumb";
152*1c60b9acSAndroid Build Coastguard Worker wsi_dumb = NULL;
153*1c60b9acSAndroid Build Coastguard Worker }
154*1c60b9acSAndroid Build Coastguard Worker if (wsi == wsi_mirror) {
155*1c60b9acSAndroid Build Coastguard Worker which = "mirror";
156*1c60b9acSAndroid Build Coastguard Worker wsi_mirror = NULL;
157*1c60b9acSAndroid Build Coastguard Worker }
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)LWS_ARRAY_SIZE(wsi_multi); n++)
160*1c60b9acSAndroid Build Coastguard Worker if (wsi == wsi_multi[n]) {
161*1c60b9acSAndroid Build Coastguard Worker sprintf(which_wsi, "multi %d", n);
162*1c60b9acSAndroid Build Coastguard Worker which = which_wsi;
163*1c60b9acSAndroid Build Coastguard Worker wsi_multi[n] = NULL;
164*1c60b9acSAndroid Build Coastguard Worker }
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker lwsl_err("CLIENT_CONNECTION_ERROR: %s: %s\n", which,
167*1c60b9acSAndroid Build Coastguard Worker in ? (char *)in : "(null)");
168*1c60b9acSAndroid Build Coastguard Worker break;
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
171*1c60b9acSAndroid Build Coastguard Worker if ((strcmp((const char *)in, "deflate-stream") == 0) &&
172*1c60b9acSAndroid Build Coastguard Worker deny_deflate) {
173*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("denied deflate-stream extension\n");
174*1c60b9acSAndroid Build Coastguard Worker return 1;
175*1c60b9acSAndroid Build Coastguard Worker }
176*1c60b9acSAndroid Build Coastguard Worker if ((strcmp((const char *)in, "x-webkit-deflate-frame") == 0))
177*1c60b9acSAndroid Build Coastguard Worker return 1;
178*1c60b9acSAndroid Build Coastguard Worker if ((strcmp((const char *)in, "deflate-frame") == 0))
179*1c60b9acSAndroid Build Coastguard Worker return 1;
180*1c60b9acSAndroid Build Coastguard Worker break;
181*1c60b9acSAndroid Build Coastguard Worker
182*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
183*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("lws_http_client_http_response %d\n",
184*1c60b9acSAndroid Build Coastguard Worker lws_http_client_http_response(wsi));
185*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
186*1c60b9acSAndroid Build Coastguard Worker if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME,
187*1c60b9acSAndroid Build Coastguard Worker &ci, sizeof(ci.ns.name)))
188*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Peer Cert CN : %s\n", ci.ns.name);
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_ISSUER_NAME,
191*1c60b9acSAndroid Build Coastguard Worker &ci, sizeof(ci.ns.name)))
192*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Peer Cert issuer : %s\n", ci.ns.name);
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_VALIDITY_FROM,
195*1c60b9acSAndroid Build Coastguard Worker &ci, 0))
196*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_CTIME_R)
197*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Peer Cert Valid from: %s",
198*1c60b9acSAndroid Build Coastguard Worker ctime_r(&ci.time, date));
199*1c60b9acSAndroid Build Coastguard Worker #else
200*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Peer Cert Valid from: %s",
201*1c60b9acSAndroid Build Coastguard Worker ctime(&ci.time));
202*1c60b9acSAndroid Build Coastguard Worker #endif
203*1c60b9acSAndroid Build Coastguard Worker if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_VALIDITY_TO,
204*1c60b9acSAndroid Build Coastguard Worker &ci, 0))
205*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_CTIME_R)
206*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Peer Cert Valid to : %s",
207*1c60b9acSAndroid Build Coastguard Worker ctime_r(&ci.time, date));
208*1c60b9acSAndroid Build Coastguard Worker #else
209*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Peer Cert Valid to : %s",
210*1c60b9acSAndroid Build Coastguard Worker ctime(&ci.time));
211*1c60b9acSAndroid Build Coastguard Worker #endif
212*1c60b9acSAndroid Build Coastguard Worker if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_USAGE,
213*1c60b9acSAndroid Build Coastguard Worker &ci, 0))
214*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Peer Cert usage bits: 0x%x\n", ci.usage);
215*1c60b9acSAndroid Build Coastguard Worker #endif
216*1c60b9acSAndroid Build Coastguard Worker break;
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker /* chunked content */
219*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
220*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: %ld\n",
221*1c60b9acSAndroid Build Coastguard Worker (long)len);
222*1c60b9acSAndroid Build Coastguard Worker show_http_content(in, len);
223*1c60b9acSAndroid Build Coastguard Worker break;
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker /* unchunked content */
226*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
227*1c60b9acSAndroid Build Coastguard Worker {
228*1c60b9acSAndroid Build Coastguard Worker char buffer[1024 + LWS_PRE];
229*1c60b9acSAndroid Build Coastguard Worker char *px = buffer + LWS_PRE;
230*1c60b9acSAndroid Build Coastguard Worker int lenx = sizeof(buffer) - LWS_PRE;
231*1c60b9acSAndroid Build Coastguard Worker
232*1c60b9acSAndroid Build Coastguard Worker /*
233*1c60b9acSAndroid Build Coastguard Worker * Often you need to flow control this by something
234*1c60b9acSAndroid Build Coastguard Worker * else being writable. In that case call the api
235*1c60b9acSAndroid Build Coastguard Worker * to get a callback when writable here, and do the
236*1c60b9acSAndroid Build Coastguard Worker * pending client read in the writeable callback of
237*1c60b9acSAndroid Build Coastguard Worker * the output.
238*1c60b9acSAndroid Build Coastguard Worker *
239*1c60b9acSAndroid Build Coastguard Worker * In the case of chunked content, this will call back
240*1c60b9acSAndroid Build Coastguard Worker * LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ once per
241*1c60b9acSAndroid Build Coastguard Worker * chunk or partial chunk in the buffer, and report
242*1c60b9acSAndroid Build Coastguard Worker * zero length back here.
243*1c60b9acSAndroid Build Coastguard Worker */
244*1c60b9acSAndroid Build Coastguard Worker if (lws_http_client_read(wsi, &px, &lenx) < 0)
245*1c60b9acSAndroid Build Coastguard Worker return -1;
246*1c60b9acSAndroid Build Coastguard Worker }
247*1c60b9acSAndroid Build Coastguard Worker break;
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_WRITEABLE:
250*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Client wsi %p writable\n", wsi);
251*1c60b9acSAndroid Build Coastguard Worker break;
252*1c60b9acSAndroid Build Coastguard Worker
253*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
254*1c60b9acSAndroid Build Coastguard Worker if (test_post) {
255*1c60b9acSAndroid Build Coastguard Worker unsigned char **p = (unsigned char **)in, *end = (*p) + len;
256*1c60b9acSAndroid Build Coastguard Worker
257*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
258*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_LENGTH,
259*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"29", 2, p, end))
260*1c60b9acSAndroid Build Coastguard Worker return -1;
261*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
262*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_TYPE,
263*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"application/x-www-form-urlencoded",
264*1c60b9acSAndroid Build Coastguard Worker 33, p, end))
265*1c60b9acSAndroid Build Coastguard Worker return -1;
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker /* inform lws we have http body to send */
268*1c60b9acSAndroid Build Coastguard Worker lws_client_http_body_pending(wsi, 1);
269*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
270*1c60b9acSAndroid Build Coastguard Worker }
271*1c60b9acSAndroid Build Coastguard Worker break;
272*1c60b9acSAndroid Build Coastguard Worker
273*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
274*1c60b9acSAndroid Build Coastguard Worker strcpy(buf + LWS_PRE, "text=hello&send=Send+the+form");
275*1c60b9acSAndroid Build Coastguard Worker n = lws_write(wsi, (unsigned char *)&buf[LWS_PRE],
276*1c60b9acSAndroid Build Coastguard Worker strlen(&buf[LWS_PRE]), LWS_WRITE_HTTP);
277*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
278*1c60b9acSAndroid Build Coastguard Worker return -1;
279*1c60b9acSAndroid Build Coastguard Worker /* we only had one thing to send, so inform lws we are done
280*1c60b9acSAndroid Build Coastguard Worker * if we had more to send, call lws_callback_on_writable(wsi);
281*1c60b9acSAndroid Build Coastguard Worker * and just return 0 from callback. On having sent the last
282*1c60b9acSAndroid Build Coastguard Worker * part, call the below api instead.*/
283*1c60b9acSAndroid Build Coastguard Worker lws_client_http_body_pending(wsi, 0);
284*1c60b9acSAndroid Build Coastguard Worker break;
285*1c60b9acSAndroid Build Coastguard Worker
286*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
287*1c60b9acSAndroid Build Coastguard Worker wsi_dumb = NULL;
288*1c60b9acSAndroid Build Coastguard Worker force_exit = 1;
289*1c60b9acSAndroid Build Coastguard Worker break;
290*1c60b9acSAndroid Build Coastguard Worker
291*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param) && \
292*1c60b9acSAndroid Build Coastguard Worker !defined(LWS_WITH_MBEDTLS)
293*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
294*1c60b9acSAndroid Build Coastguard Worker if (crl_path[0]) {
295*1c60b9acSAndroid Build Coastguard Worker /* Enable CRL checking of the server certificate */
296*1c60b9acSAndroid Build Coastguard Worker X509_STORE *store;
297*1c60b9acSAndroid Build Coastguard Worker X509_LOOKUP *lookup;
298*1c60b9acSAndroid Build Coastguard Worker int n;
299*1c60b9acSAndroid Build Coastguard Worker X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
300*1c60b9acSAndroid Build Coastguard Worker X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
301*1c60b9acSAndroid Build Coastguard Worker SSL_CTX_set1_param((SSL_CTX*)user, param);
302*1c60b9acSAndroid Build Coastguard Worker store = SSL_CTX_get_cert_store((SSL_CTX*)user);
303*1c60b9acSAndroid Build Coastguard Worker lookup = X509_STORE_add_lookup(store,
304*1c60b9acSAndroid Build Coastguard Worker X509_LOOKUP_file());
305*1c60b9acSAndroid Build Coastguard Worker n = X509_load_cert_crl_file(lookup, crl_path,
306*1c60b9acSAndroid Build Coastguard Worker X509_FILETYPE_PEM);
307*1c60b9acSAndroid Build Coastguard Worker X509_VERIFY_PARAM_free(param);
308*1c60b9acSAndroid Build Coastguard Worker if (n != 1) {
309*1c60b9acSAndroid Build Coastguard Worker char errbuf[256];
310*1c60b9acSAndroid Build Coastguard Worker const char *es;
311*1c60b9acSAndroid Build Coastguard Worker
312*1c60b9acSAndroid Build Coastguard Worker n = (int)ERR_get_error();
313*1c60b9acSAndroid Build Coastguard Worker es = ERR_error_string(
314*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
315*1c60b9acSAndroid Build Coastguard Worker (uint32_t)
316*1c60b9acSAndroid Build Coastguard Worker #else
317*1c60b9acSAndroid Build Coastguard Worker (unsigned long)
318*1c60b9acSAndroid Build Coastguard Worker #endif
319*1c60b9acSAndroid Build Coastguard Worker n, errbuf);
320*1c60b9acSAndroid Build Coastguard Worker lwsl_err("EXTRA_CLIENT_VERIFY_CERTS: "
321*1c60b9acSAndroid Build Coastguard Worker "SSL error: %s (%d)\n", es, n);
322*1c60b9acSAndroid Build Coastguard Worker return 1;
323*1c60b9acSAndroid Build Coastguard Worker }
324*1c60b9acSAndroid Build Coastguard Worker }
325*1c60b9acSAndroid Build Coastguard Worker break;
326*1c60b9acSAndroid Build Coastguard Worker #endif
327*1c60b9acSAndroid Build Coastguard Worker
328*1c60b9acSAndroid Build Coastguard Worker default:
329*1c60b9acSAndroid Build Coastguard Worker break;
330*1c60b9acSAndroid Build Coastguard Worker }
331*1c60b9acSAndroid Build Coastguard Worker
332*1c60b9acSAndroid Build Coastguard Worker return 0;
333*1c60b9acSAndroid Build Coastguard Worker }
334*1c60b9acSAndroid Build Coastguard Worker
335*1c60b9acSAndroid Build Coastguard Worker
336*1c60b9acSAndroid Build Coastguard Worker /* lws-mirror_protocol */
337*1c60b9acSAndroid Build Coastguard Worker
338*1c60b9acSAndroid Build Coastguard Worker
339*1c60b9acSAndroid Build Coastguard Worker static int
callback_lws_mirror(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)340*1c60b9acSAndroid Build Coastguard Worker callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
341*1c60b9acSAndroid Build Coastguard Worker void *user, void *in, size_t len)
342*1c60b9acSAndroid Build Coastguard Worker {
343*1c60b9acSAndroid Build Coastguard Worker unsigned char buf[LWS_PRE + block_size], *p;
344*1c60b9acSAndroid Build Coastguard Worker unsigned int rands[4];
345*1c60b9acSAndroid Build Coastguard Worker int l = 0;
346*1c60b9acSAndroid Build Coastguard Worker int n;
347*1c60b9acSAndroid Build Coastguard Worker
348*1c60b9acSAndroid Build Coastguard Worker switch (reason) {
349*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_ESTABLISHED:
350*1c60b9acSAndroid Build Coastguard Worker
351*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("mirror: LWS_CALLBACK_CLIENT_ESTABLISHED\n");
352*1c60b9acSAndroid Build Coastguard Worker
353*1c60b9acSAndroid Build Coastguard Worker if (flag_echo) {
354*1c60b9acSAndroid Build Coastguard Worker rxb = txb = 0;
355*1c60b9acSAndroid Build Coastguard Worker rx.cyc[0] = tx.cyc[0] = 0xabcde;
356*1c60b9acSAndroid Build Coastguard Worker rx.cyc[1] = tx.cyc[1] = 0x23456789;
357*1c60b9acSAndroid Build Coastguard Worker
358*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
359*1c60b9acSAndroid Build Coastguard Worker
360*1c60b9acSAndroid Build Coastguard Worker break;
361*1c60b9acSAndroid Build Coastguard Worker }
362*1c60b9acSAndroid Build Coastguard Worker
363*1c60b9acSAndroid Build Coastguard Worker lws_get_random(lws_get_context(wsi), rands, sizeof(rands[0]));
364*1c60b9acSAndroid Build Coastguard Worker mirror_lifetime = (int)(16384 + (rands[0] & 65535));
365*1c60b9acSAndroid Build Coastguard Worker /* useful to test single connection stability */
366*1c60b9acSAndroid Build Coastguard Worker if (longlived)
367*1c60b9acSAndroid Build Coastguard Worker mirror_lifetime += 500000;
368*1c60b9acSAndroid Build Coastguard Worker
369*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("opened mirror connection with "
370*1c60b9acSAndroid Build Coastguard Worker "%d lifetime\n", mirror_lifetime);
371*1c60b9acSAndroid Build Coastguard Worker
372*1c60b9acSAndroid Build Coastguard Worker /*
373*1c60b9acSAndroid Build Coastguard Worker * mirror_lifetime is decremented each send, when it reaches
374*1c60b9acSAndroid Build Coastguard Worker * zero the connection is closed in the send callback.
375*1c60b9acSAndroid Build Coastguard Worker * When the close callback comes, wsi_mirror is set to NULL
376*1c60b9acSAndroid Build Coastguard Worker * so a new connection will be opened
377*1c60b9acSAndroid Build Coastguard Worker *
378*1c60b9acSAndroid Build Coastguard Worker * start the ball rolling,
379*1c60b9acSAndroid Build Coastguard Worker * LWS_CALLBACK_CLIENT_WRITEABLE will come next service
380*1c60b9acSAndroid Build Coastguard Worker */
381*1c60b9acSAndroid Build Coastguard Worker if (!flag_no_mirror_traffic)
382*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
383*1c60b9acSAndroid Build Coastguard Worker break;
384*1c60b9acSAndroid Build Coastguard Worker
385*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_CLOSED:
386*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("mirror: LWS_CALLBACK_CLOSED mirror_lifetime=%d, "
387*1c60b9acSAndroid Build Coastguard Worker "rxb %d, rx_count %d\n", mirror_lifetime, rxb,
388*1c60b9acSAndroid Build Coastguard Worker rx_count);
389*1c60b9acSAndroid Build Coastguard Worker wsi_mirror = NULL;
390*1c60b9acSAndroid Build Coastguard Worker if (flag_echo || once)
391*1c60b9acSAndroid Build Coastguard Worker force_exit = 1;
392*1c60b9acSAndroid Build Coastguard Worker break;
393*1c60b9acSAndroid Build Coastguard Worker
394*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_WRITEABLE:
395*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS_CALLBACK_CLIENT_WRITEABLE\n");
396*1c60b9acSAndroid Build Coastguard Worker if (flag_no_mirror_traffic)
397*1c60b9acSAndroid Build Coastguard Worker return 0;
398*1c60b9acSAndroid Build Coastguard Worker
399*1c60b9acSAndroid Build Coastguard Worker if (flag_echo) {
400*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)block_size; n++)
401*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE + n] = lws_poly_rand(&tx);
402*1c60b9acSAndroid Build Coastguard Worker
403*1c60b9acSAndroid Build Coastguard Worker n = lws_write(wsi, &buf[LWS_PRE], block_size,
404*1c60b9acSAndroid Build Coastguard Worker opts | LWS_WRITE_TEXT);
405*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
406*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Error sending\n");
407*1c60b9acSAndroid Build Coastguard Worker return -1;
408*1c60b9acSAndroid Build Coastguard Worker }
409*1c60b9acSAndroid Build Coastguard Worker
410*1c60b9acSAndroid Build Coastguard Worker txb++;
411*1c60b9acSAndroid Build Coastguard Worker if (txb != count_blocks)
412*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
413*1c60b9acSAndroid Build Coastguard Worker else {
414*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("send completed: %d x %d\n",
415*1c60b9acSAndroid Build Coastguard Worker count_blocks, block_size);
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker break;
418*1c60b9acSAndroid Build Coastguard Worker }
419*1c60b9acSAndroid Build Coastguard Worker
420*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < 1; n++) {
421*1c60b9acSAndroid Build Coastguard Worker lws_get_random(lws_get_context(wsi), rands,
422*1c60b9acSAndroid Build Coastguard Worker sizeof(rands));
423*1c60b9acSAndroid Build Coastguard Worker l += sprintf((char *)&buf[LWS_PRE + l],
424*1c60b9acSAndroid Build Coastguard Worker "c #%06X %u %u %u;",
425*1c60b9acSAndroid Build Coastguard Worker rands[0] & 0xffffff, /* colour */
426*1c60b9acSAndroid Build Coastguard Worker rands[1] & 511, /* x */
427*1c60b9acSAndroid Build Coastguard Worker rands[2] & 255, /* y */
428*1c60b9acSAndroid Build Coastguard Worker (rands[3] & 31) + 1); /* radius */
429*1c60b9acSAndroid Build Coastguard Worker }
430*1c60b9acSAndroid Build Coastguard Worker
431*1c60b9acSAndroid Build Coastguard Worker n = (int)lws_write(wsi, &buf[LWS_PRE], (unsigned int)l,
432*1c60b9acSAndroid Build Coastguard Worker opts | LWS_WRITE_TEXT);
433*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
434*1c60b9acSAndroid Build Coastguard Worker return -1;
435*1c60b9acSAndroid Build Coastguard Worker if (n < l) {
436*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Partial write LWS_CALLBACK_CLIENT_WRITEABLE\n");
437*1c60b9acSAndroid Build Coastguard Worker return -1;
438*1c60b9acSAndroid Build Coastguard Worker }
439*1c60b9acSAndroid Build Coastguard Worker if (!justmirror)
440*1c60b9acSAndroid Build Coastguard Worker mirror_lifetime--;
441*1c60b9acSAndroid Build Coastguard Worker if (!mirror_lifetime) {
442*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("closing mirror session\n");
443*1c60b9acSAndroid Build Coastguard Worker return -1;
444*1c60b9acSAndroid Build Coastguard Worker }
445*1c60b9acSAndroid Build Coastguard Worker /* get notified as soon as we can write again */
446*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
447*1c60b9acSAndroid Build Coastguard Worker
448*1c60b9acSAndroid Build Coastguard Worker #if !defined(_WIN32) && !defined(WIN32)
449*1c60b9acSAndroid Build Coastguard Worker usleep(50);
450*1c60b9acSAndroid Build Coastguard Worker #endif
451*1c60b9acSAndroid Build Coastguard Worker break;
452*1c60b9acSAndroid Build Coastguard Worker
453*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_RECEIVE:
454*1c60b9acSAndroid Build Coastguard Worker if (flag_echo) {
455*1c60b9acSAndroid Build Coastguard Worker p = (unsigned char *)in;
456*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)len; n++)
457*1c60b9acSAndroid Build Coastguard Worker if (*p++ != lws_poly_rand(&rx)) {
458*1c60b9acSAndroid Build Coastguard Worker lwsl_err("mismatch at rxb %d offset %d\n", (int)rxb + (n / block_size), n % block_size);
459*1c60b9acSAndroid Build Coastguard Worker errs++;
460*1c60b9acSAndroid Build Coastguard Worker force_exit = 1;
461*1c60b9acSAndroid Build Coastguard Worker return -1;
462*1c60b9acSAndroid Build Coastguard Worker }
463*1c60b9acSAndroid Build Coastguard Worker rx_count += (unsigned int)(unsigned long long)len;
464*1c60b9acSAndroid Build Coastguard Worker while (rx_count >= block_size) {
465*1c60b9acSAndroid Build Coastguard Worker rx_count -= block_size;
466*1c60b9acSAndroid Build Coastguard Worker rxb++;
467*1c60b9acSAndroid Build Coastguard Worker }
468*1c60b9acSAndroid Build Coastguard Worker if (rx_count == 0 && rxb == count_blocks) {
469*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("Everything received: errs %d\n",
470*1c60b9acSAndroid Build Coastguard Worker errs);
471*1c60b9acSAndroid Build Coastguard Worker force_exit = 1;
472*1c60b9acSAndroid Build Coastguard Worker return -1;
473*1c60b9acSAndroid Build Coastguard Worker }
474*1c60b9acSAndroid Build Coastguard Worker }
475*1c60b9acSAndroid Build Coastguard Worker break;
476*1c60b9acSAndroid Build Coastguard Worker default:
477*1c60b9acSAndroid Build Coastguard Worker break;
478*1c60b9acSAndroid Build Coastguard Worker }
479*1c60b9acSAndroid Build Coastguard Worker
480*1c60b9acSAndroid Build Coastguard Worker return 0;
481*1c60b9acSAndroid Build Coastguard Worker }
482*1c60b9acSAndroid Build Coastguard Worker
483*1c60b9acSAndroid Build Coastguard Worker static int
callback_test_raw_client(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)484*1c60b9acSAndroid Build Coastguard Worker callback_test_raw_client(struct lws *wsi, enum lws_callback_reasons reason,
485*1c60b9acSAndroid Build Coastguard Worker void *user, void *in, size_t len)
486*1c60b9acSAndroid Build Coastguard Worker {
487*1c60b9acSAndroid Build Coastguard Worker switch (reason) {
488*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_ADOPT:
489*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_ADOPT\n");
490*1c60b9acSAndroid Build Coastguard Worker break;
491*1c60b9acSAndroid Build Coastguard Worker
492*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_RX:
493*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_RX %ld\n", (long)len);
494*1c60b9acSAndroid Build Coastguard Worker puts(in);
495*1c60b9acSAndroid Build Coastguard Worker break;
496*1c60b9acSAndroid Build Coastguard Worker
497*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_CLOSE:
498*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_CLOSE\n");
499*1c60b9acSAndroid Build Coastguard Worker break;
500*1c60b9acSAndroid Build Coastguard Worker
501*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_WRITEABLE:
502*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE\n");
503*1c60b9acSAndroid Build Coastguard Worker break;
504*1c60b9acSAndroid Build Coastguard Worker
505*1c60b9acSAndroid Build Coastguard Worker default:
506*1c60b9acSAndroid Build Coastguard Worker break;
507*1c60b9acSAndroid Build Coastguard Worker }
508*1c60b9acSAndroid Build Coastguard Worker
509*1c60b9acSAndroid Build Coastguard Worker return 0;
510*1c60b9acSAndroid Build Coastguard Worker }
511*1c60b9acSAndroid Build Coastguard Worker
512*1c60b9acSAndroid Build Coastguard Worker /* list of supported protocols and callbacks */
513*1c60b9acSAndroid Build Coastguard Worker
514*1c60b9acSAndroid Build Coastguard Worker static const struct lws_protocols protocols[] = {
515*1c60b9acSAndroid Build Coastguard Worker {
516*1c60b9acSAndroid Build Coastguard Worker "dumb-increment-protocol",
517*1c60b9acSAndroid Build Coastguard Worker callback_dumb_increment,
518*1c60b9acSAndroid Build Coastguard Worker 0, 20, 0, NULL, 0
519*1c60b9acSAndroid Build Coastguard Worker },
520*1c60b9acSAndroid Build Coastguard Worker {
521*1c60b9acSAndroid Build Coastguard Worker "lws-mirror-protocol",
522*1c60b9acSAndroid Build Coastguard Worker callback_lws_mirror,
523*1c60b9acSAndroid Build Coastguard Worker 0, 4096, 0, NULL, 0
524*1c60b9acSAndroid Build Coastguard Worker }, {
525*1c60b9acSAndroid Build Coastguard Worker "lws-test-raw-client",
526*1c60b9acSAndroid Build Coastguard Worker callback_test_raw_client,
527*1c60b9acSAndroid Build Coastguard Worker 0, 128, 0, NULL, 0
528*1c60b9acSAndroid Build Coastguard Worker },
529*1c60b9acSAndroid Build Coastguard Worker LWS_PROTOCOL_LIST_TERM
530*1c60b9acSAndroid Build Coastguard Worker };
531*1c60b9acSAndroid Build Coastguard Worker
532*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
533*1c60b9acSAndroid Build Coastguard Worker static const struct lws_extension exts[] = {
534*1c60b9acSAndroid Build Coastguard Worker {
535*1c60b9acSAndroid Build Coastguard Worker "permessage-deflate",
536*1c60b9acSAndroid Build Coastguard Worker lws_extension_callback_pm_deflate,
537*1c60b9acSAndroid Build Coastguard Worker "permessage-deflate; client_no_context_takeover"
538*1c60b9acSAndroid Build Coastguard Worker },
539*1c60b9acSAndroid Build Coastguard Worker {
540*1c60b9acSAndroid Build Coastguard Worker "deflate-frame",
541*1c60b9acSAndroid Build Coastguard Worker lws_extension_callback_pm_deflate,
542*1c60b9acSAndroid Build Coastguard Worker "deflate_frame"
543*1c60b9acSAndroid Build Coastguard Worker },
544*1c60b9acSAndroid Build Coastguard Worker { NULL, NULL, NULL /* terminator */ }
545*1c60b9acSAndroid Build Coastguard Worker };
546*1c60b9acSAndroid Build Coastguard Worker #endif
547*1c60b9acSAndroid Build Coastguard Worker
548*1c60b9acSAndroid Build Coastguard Worker
sighandler(int sig)549*1c60b9acSAndroid Build Coastguard Worker void sighandler(int sig)
550*1c60b9acSAndroid Build Coastguard Worker {
551*1c60b9acSAndroid Build Coastguard Worker force_exit = 1;
552*1c60b9acSAndroid Build Coastguard Worker }
553*1c60b9acSAndroid Build Coastguard Worker
554*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32)
555*1c60b9acSAndroid Build Coastguard Worker static struct option options[] = {
556*1c60b9acSAndroid Build Coastguard Worker { "help", no_argument, NULL, 'h' },
557*1c60b9acSAndroid Build Coastguard Worker { "debug", required_argument, NULL, 'd' },
558*1c60b9acSAndroid Build Coastguard Worker { "port", required_argument, NULL, 'p' },
559*1c60b9acSAndroid Build Coastguard Worker { "ssl", no_argument, NULL, 's' },
560*1c60b9acSAndroid Build Coastguard Worker { "strict-ssl", no_argument, NULL, 'S' },
561*1c60b9acSAndroid Build Coastguard Worker { "version", required_argument, NULL, 'v' },
562*1c60b9acSAndroid Build Coastguard Worker { "undeflated", no_argument, NULL, 'u' },
563*1c60b9acSAndroid Build Coastguard Worker { "echo", no_argument, NULL, 'e' },
564*1c60b9acSAndroid Build Coastguard Worker { "multi-test", no_argument, NULL, 'm' },
565*1c60b9acSAndroid Build Coastguard Worker { "nomirror", no_argument, NULL, 'n' },
566*1c60b9acSAndroid Build Coastguard Worker { "justmirror", no_argument, NULL, 'j' },
567*1c60b9acSAndroid Build Coastguard Worker { "longlived", no_argument, NULL, 'l' },
568*1c60b9acSAndroid Build Coastguard Worker { "post", no_argument, NULL, 'o' },
569*1c60b9acSAndroid Build Coastguard Worker { "once", no_argument, NULL, 'O' },
570*1c60b9acSAndroid Build Coastguard Worker { "ssl-cert", required_argument, NULL, 'C' },
571*1c60b9acSAndroid Build Coastguard Worker { "ssl-key", required_argument, NULL, 'K' },
572*1c60b9acSAndroid Build Coastguard Worker { "ssl-ca", required_argument, NULL, 'A' },
573*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
574*1c60b9acSAndroid Build Coastguard Worker { "ssl-crl", required_argument, NULL, 'R' },
575*1c60b9acSAndroid Build Coastguard Worker #endif
576*1c60b9acSAndroid Build Coastguard Worker { NULL, 0, 0, 0 }
577*1c60b9acSAndroid Build Coastguard Worker };
578*1c60b9acSAndroid Build Coastguard Worker #endif
579*1c60b9acSAndroid Build Coastguard Worker
ratelimit_connects(unsigned int * last,unsigned int secs)580*1c60b9acSAndroid Build Coastguard Worker static int ratelimit_connects(unsigned int *last, unsigned int secs)
581*1c60b9acSAndroid Build Coastguard Worker {
582*1c60b9acSAndroid Build Coastguard Worker struct timeval tv;
583*1c60b9acSAndroid Build Coastguard Worker
584*1c60b9acSAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
585*1c60b9acSAndroid Build Coastguard Worker
586*1c60b9acSAndroid Build Coastguard Worker if ((unsigned long)tv.tv_sec - (unsigned long)(*last) < (unsigned long)secs)
587*1c60b9acSAndroid Build Coastguard Worker return 0;
588*1c60b9acSAndroid Build Coastguard Worker
589*1c60b9acSAndroid Build Coastguard Worker *last = (unsigned int)tv.tv_sec;
590*1c60b9acSAndroid Build Coastguard Worker
591*1c60b9acSAndroid Build Coastguard Worker return 1;
592*1c60b9acSAndroid Build Coastguard Worker }
593*1c60b9acSAndroid Build Coastguard Worker
main(int argc,char ** argv)594*1c60b9acSAndroid Build Coastguard Worker int main(int argc, char **argv)
595*1c60b9acSAndroid Build Coastguard Worker {
596*1c60b9acSAndroid Build Coastguard Worker int n = 0, m, ret = 0, port = 7681, use_ssl = 0, ietf_version = -1;
597*1c60b9acSAndroid Build Coastguard Worker unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, do_multi = 0;
598*1c60b9acSAndroid Build Coastguard Worker struct lws_context_creation_info info;
599*1c60b9acSAndroid Build Coastguard Worker struct lws_client_connect_info i;
600*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context;
601*1c60b9acSAndroid Build Coastguard Worker const char *prot, *p;
602*1c60b9acSAndroid Build Coastguard Worker char path[300];
603*1c60b9acSAndroid Build Coastguard Worker char cert_path[1024] = "";
604*1c60b9acSAndroid Build Coastguard Worker char key_path[1024] = "";
605*1c60b9acSAndroid Build Coastguard Worker char ca_path[1024] = "";
606*1c60b9acSAndroid Build Coastguard Worker unsigned long last = lws_now_secs();
607*1c60b9acSAndroid Build Coastguard Worker
608*1c60b9acSAndroid Build Coastguard Worker memset(&info, 0, sizeof info);
609*1c60b9acSAndroid Build Coastguard Worker
610*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("libwebsockets test client - license MIT\n");
611*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("(C) Copyright 2010-2018 Andy Green <[email protected]>\n");
612*1c60b9acSAndroid Build Coastguard Worker
613*1c60b9acSAndroid Build Coastguard Worker if (argc < 2)
614*1c60b9acSAndroid Build Coastguard Worker goto usage;
615*1c60b9acSAndroid Build Coastguard Worker
616*1c60b9acSAndroid Build Coastguard Worker while (n >= 0) {
617*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32)
618*1c60b9acSAndroid Build Coastguard Worker n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:moeO", options, NULL);
619*1c60b9acSAndroid Build Coastguard Worker #else
620*1c60b9acSAndroid Build Coastguard Worker n = getopt(argc, argv, "Sjnuv:hsp:d:lC:K:A:moeO");
621*1c60b9acSAndroid Build Coastguard Worker #endif
622*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
623*1c60b9acSAndroid Build Coastguard Worker continue;
624*1c60b9acSAndroid Build Coastguard Worker switch (n) {
625*1c60b9acSAndroid Build Coastguard Worker case 'd':
626*1c60b9acSAndroid Build Coastguard Worker lws_set_log_level(atoi(optarg), NULL);
627*1c60b9acSAndroid Build Coastguard Worker break;
628*1c60b9acSAndroid Build Coastguard Worker case 's': /* lax SSL, allow selfsigned, skip checking hostname */
629*1c60b9acSAndroid Build Coastguard Worker use_ssl = LCCSCF_USE_SSL |
630*1c60b9acSAndroid Build Coastguard Worker LCCSCF_ALLOW_SELFSIGNED |
631*1c60b9acSAndroid Build Coastguard Worker LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
632*1c60b9acSAndroid Build Coastguard Worker break;
633*1c60b9acSAndroid Build Coastguard Worker case 'S': /* Strict SSL, no selfsigned, check server hostname */
634*1c60b9acSAndroid Build Coastguard Worker use_ssl = LCCSCF_USE_SSL;
635*1c60b9acSAndroid Build Coastguard Worker break;
636*1c60b9acSAndroid Build Coastguard Worker case 'p':
637*1c60b9acSAndroid Build Coastguard Worker port = atoi(optarg);
638*1c60b9acSAndroid Build Coastguard Worker break;
639*1c60b9acSAndroid Build Coastguard Worker case 'e':
640*1c60b9acSAndroid Build Coastguard Worker flag_echo = 1;
641*1c60b9acSAndroid Build Coastguard Worker break;
642*1c60b9acSAndroid Build Coastguard Worker case 'j':
643*1c60b9acSAndroid Build Coastguard Worker justmirror = 1;
644*1c60b9acSAndroid Build Coastguard Worker break;
645*1c60b9acSAndroid Build Coastguard Worker case 'l':
646*1c60b9acSAndroid Build Coastguard Worker longlived = 1;
647*1c60b9acSAndroid Build Coastguard Worker break;
648*1c60b9acSAndroid Build Coastguard Worker case 'v':
649*1c60b9acSAndroid Build Coastguard Worker ietf_version = atoi(optarg);
650*1c60b9acSAndroid Build Coastguard Worker break;
651*1c60b9acSAndroid Build Coastguard Worker case 'u':
652*1c60b9acSAndroid Build Coastguard Worker deny_deflate = 1;
653*1c60b9acSAndroid Build Coastguard Worker break;
654*1c60b9acSAndroid Build Coastguard Worker case 'm':
655*1c60b9acSAndroid Build Coastguard Worker do_multi = 1;
656*1c60b9acSAndroid Build Coastguard Worker break;
657*1c60b9acSAndroid Build Coastguard Worker case 'o':
658*1c60b9acSAndroid Build Coastguard Worker test_post = 1;
659*1c60b9acSAndroid Build Coastguard Worker break;
660*1c60b9acSAndroid Build Coastguard Worker case 'O':
661*1c60b9acSAndroid Build Coastguard Worker once = 1;
662*1c60b9acSAndroid Build Coastguard Worker break;
663*1c60b9acSAndroid Build Coastguard Worker case 'n':
664*1c60b9acSAndroid Build Coastguard Worker flag_no_mirror_traffic = 1;
665*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("Disabled sending mirror data (for pingpong testing)\n");
666*1c60b9acSAndroid Build Coastguard Worker break;
667*1c60b9acSAndroid Build Coastguard Worker case 'C':
668*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(cert_path, optarg, sizeof(cert_path));
669*1c60b9acSAndroid Build Coastguard Worker break;
670*1c60b9acSAndroid Build Coastguard Worker case 'K':
671*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(key_path, optarg, sizeof(key_path));
672*1c60b9acSAndroid Build Coastguard Worker break;
673*1c60b9acSAndroid Build Coastguard Worker case 'A':
674*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(ca_path, optarg, sizeof(ca_path));
675*1c60b9acSAndroid Build Coastguard Worker break;
676*1c60b9acSAndroid Build Coastguard Worker
677*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
678*1c60b9acSAndroid Build Coastguard Worker case 'R':
679*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(crl_path, optarg, sizeof(crl_path));
680*1c60b9acSAndroid Build Coastguard Worker break;
681*1c60b9acSAndroid Build Coastguard Worker #endif
682*1c60b9acSAndroid Build Coastguard Worker case 'h':
683*1c60b9acSAndroid Build Coastguard Worker goto usage;
684*1c60b9acSAndroid Build Coastguard Worker }
685*1c60b9acSAndroid Build Coastguard Worker }
686*1c60b9acSAndroid Build Coastguard Worker
687*1c60b9acSAndroid Build Coastguard Worker if (optind >= argc)
688*1c60b9acSAndroid Build Coastguard Worker goto usage;
689*1c60b9acSAndroid Build Coastguard Worker
690*1c60b9acSAndroid Build Coastguard Worker signal(SIGINT, sighandler);
691*1c60b9acSAndroid Build Coastguard Worker
692*1c60b9acSAndroid Build Coastguard Worker memset(&i, 0, sizeof(i));
693*1c60b9acSAndroid Build Coastguard Worker
694*1c60b9acSAndroid Build Coastguard Worker i.port = port;
695*1c60b9acSAndroid Build Coastguard Worker if (lws_parse_uri(argv[optind], &prot, &i.address, &i.port, &p))
696*1c60b9acSAndroid Build Coastguard Worker goto usage;
697*1c60b9acSAndroid Build Coastguard Worker
698*1c60b9acSAndroid Build Coastguard Worker /* add back the leading / on path */
699*1c60b9acSAndroid Build Coastguard Worker if (p[0] != '/') {
700*1c60b9acSAndroid Build Coastguard Worker path[0] = '/';
701*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(path + 1, p, sizeof(path) - 1);
702*1c60b9acSAndroid Build Coastguard Worker i.path = path;
703*1c60b9acSAndroid Build Coastguard Worker } else
704*1c60b9acSAndroid Build Coastguard Worker i.path = p;
705*1c60b9acSAndroid Build Coastguard Worker
706*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(prot, "http") || !strcmp(prot, "ws"))
707*1c60b9acSAndroid Build Coastguard Worker use_ssl = 0;
708*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(prot, "https") || !strcmp(prot, "wss"))
709*1c60b9acSAndroid Build Coastguard Worker if (!use_ssl)
710*1c60b9acSAndroid Build Coastguard Worker use_ssl = LCCSCF_USE_SSL;
711*1c60b9acSAndroid Build Coastguard Worker
712*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("'%s' %p '%s' %p\n", i.address, i.address, i.path, i.path);
713*1c60b9acSAndroid Build Coastguard Worker
714*1c60b9acSAndroid Build Coastguard Worker /*
715*1c60b9acSAndroid Build Coastguard Worker * create the websockets context. This tracks open connections and
716*1c60b9acSAndroid Build Coastguard Worker * knows how to route any traffic and which protocol version to use,
717*1c60b9acSAndroid Build Coastguard Worker * and if each connection is client or server side.
718*1c60b9acSAndroid Build Coastguard Worker *
719*1c60b9acSAndroid Build Coastguard Worker * For this client-only demo, we tell it to not listen on any port.
720*1c60b9acSAndroid Build Coastguard Worker */
721*1c60b9acSAndroid Build Coastguard Worker
722*1c60b9acSAndroid Build Coastguard Worker info.port = CONTEXT_PORT_NO_LISTEN;
723*1c60b9acSAndroid Build Coastguard Worker info.protocols = protocols;
724*1c60b9acSAndroid Build Coastguard Worker info.gid = (gid_t)-1;
725*1c60b9acSAndroid Build Coastguard Worker info.uid = (uid_t)-1;
726*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
727*1c60b9acSAndroid Build Coastguard Worker info.extensions = exts;
728*1c60b9acSAndroid Build Coastguard Worker #endif
729*1c60b9acSAndroid Build Coastguard Worker
730*1c60b9acSAndroid Build Coastguard Worker /*
731*1c60b9acSAndroid Build Coastguard Worker * since we know this lws context is only ever going to be used with
732*1c60b9acSAndroid Build Coastguard Worker * a few client wsis / fds / sockets at a time, let lws know it doesn't
733*1c60b9acSAndroid Build Coastguard Worker * have to use the default allocations for fd tables up to ulimit -n.
734*1c60b9acSAndroid Build Coastguard Worker * It will just allocate for 2 internal and 4 that we might use.
735*1c60b9acSAndroid Build Coastguard Worker */
736*1c60b9acSAndroid Build Coastguard Worker info.fd_limit_per_thread = 2 + 4;
737*1c60b9acSAndroid Build Coastguard Worker
738*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
739*1c60b9acSAndroid Build Coastguard Worker info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
740*1c60b9acSAndroid Build Coastguard Worker #endif
741*1c60b9acSAndroid Build Coastguard Worker
742*1c60b9acSAndroid Build Coastguard Worker info.options |= LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW;
743*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
744*1c60b9acSAndroid Build Coastguard Worker if (use_ssl) {
745*1c60b9acSAndroid Build Coastguard Worker /*
746*1c60b9acSAndroid Build Coastguard Worker * If the server wants us to present a valid SSL client certificate
747*1c60b9acSAndroid Build Coastguard Worker * then we can set it up here.
748*1c60b9acSAndroid Build Coastguard Worker */
749*1c60b9acSAndroid Build Coastguard Worker
750*1c60b9acSAndroid Build Coastguard Worker if (cert_path[0])
751*1c60b9acSAndroid Build Coastguard Worker info.client_ssl_cert_filepath = cert_path;
752*1c60b9acSAndroid Build Coastguard Worker if (key_path[0])
753*1c60b9acSAndroid Build Coastguard Worker info.client_ssl_private_key_filepath = key_path;
754*1c60b9acSAndroid Build Coastguard Worker
755*1c60b9acSAndroid Build Coastguard Worker /*
756*1c60b9acSAndroid Build Coastguard Worker * A CA cert and CRL can be used to validate the cert send by the server
757*1c60b9acSAndroid Build Coastguard Worker */
758*1c60b9acSAndroid Build Coastguard Worker if (ca_path[0])
759*1c60b9acSAndroid Build Coastguard Worker info.client_ssl_ca_filepath = ca_path;
760*1c60b9acSAndroid Build Coastguard Worker
761*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
762*1c60b9acSAndroid Build Coastguard Worker else if (crl_path[0])
763*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("WARNING, providing a CRL requires a CA cert!\n");
764*1c60b9acSAndroid Build Coastguard Worker #endif
765*1c60b9acSAndroid Build Coastguard Worker }
766*1c60b9acSAndroid Build Coastguard Worker
767*1c60b9acSAndroid Build Coastguard Worker if (use_ssl & LCCSCF_USE_SSL) {
768*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Using SSL\n");
769*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_MBEDTLS)
770*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" (NOTE: mbedtls needs to be given the remote\n");
771*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" CA cert to trust (with -A) to validate it)\n");
772*1c60b9acSAndroid Build Coastguard Worker #endif
773*1c60b9acSAndroid Build Coastguard Worker }
774*1c60b9acSAndroid Build Coastguard Worker else
775*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" SSL disabled\n");
776*1c60b9acSAndroid Build Coastguard Worker if (use_ssl & LCCSCF_ALLOW_SELFSIGNED)
777*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Selfsigned certs allowed\n");
778*1c60b9acSAndroid Build Coastguard Worker else
779*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Cert must validate correctly (use -s to allow selfsigned)\n");
780*1c60b9acSAndroid Build Coastguard Worker if (use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)
781*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Skipping peer cert hostname check\n");
782*1c60b9acSAndroid Build Coastguard Worker else
783*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" Requiring peer cert hostname matches\n");
784*1c60b9acSAndroid Build Coastguard Worker #endif
785*1c60b9acSAndroid Build Coastguard Worker context = lws_create_context(&info);
786*1c60b9acSAndroid Build Coastguard Worker if (context == NULL) {
787*1c60b9acSAndroid Build Coastguard Worker fprintf(stderr, "Creating libwebsocket context failed\n");
788*1c60b9acSAndroid Build Coastguard Worker return 1;
789*1c60b9acSAndroid Build Coastguard Worker }
790*1c60b9acSAndroid Build Coastguard Worker
791*1c60b9acSAndroid Build Coastguard Worker i.context = context;
792*1c60b9acSAndroid Build Coastguard Worker i.ssl_connection = use_ssl;
793*1c60b9acSAndroid Build Coastguard Worker i.host = i.address;
794*1c60b9acSAndroid Build Coastguard Worker i.origin = i.address;
795*1c60b9acSAndroid Build Coastguard Worker i.ietf_version_or_minus_one = ietf_version;
796*1c60b9acSAndroid Build Coastguard Worker
797*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(prot, "http") || !strcmp(prot, "https")) {
798*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("using %s mode (non-ws)\n", prot);
799*1c60b9acSAndroid Build Coastguard Worker if (test_post) {
800*1c60b9acSAndroid Build Coastguard Worker i.method = "POST";
801*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("POST mode\n");
802*1c60b9acSAndroid Build Coastguard Worker }
803*1c60b9acSAndroid Build Coastguard Worker else
804*1c60b9acSAndroid Build Coastguard Worker i.method = "GET";
805*1c60b9acSAndroid Build Coastguard Worker do_ws = 0;
806*1c60b9acSAndroid Build Coastguard Worker } else
807*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(prot, "raw")) {
808*1c60b9acSAndroid Build Coastguard Worker i.method = "RAW";
809*1c60b9acSAndroid Build Coastguard Worker i.protocol = "lws-test-raw-client";
810*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("using RAW mode connection\n");
811*1c60b9acSAndroid Build Coastguard Worker do_ws = 0;
812*1c60b9acSAndroid Build Coastguard Worker } else
813*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("using %s mode (ws)\n", prot);
814*1c60b9acSAndroid Build Coastguard Worker
815*1c60b9acSAndroid Build Coastguard Worker /*
816*1c60b9acSAndroid Build Coastguard Worker * sit there servicing the websocket context to handle incoming
817*1c60b9acSAndroid Build Coastguard Worker * packets, and drawing random circles on the mirror protocol websocket
818*1c60b9acSAndroid Build Coastguard Worker *
819*1c60b9acSAndroid Build Coastguard Worker * nothing happens until the client websocket connection is
820*1c60b9acSAndroid Build Coastguard Worker * asynchronously established... calling lws_client_connect() only
821*1c60b9acSAndroid Build Coastguard Worker * instantiates the connection logically, lws_service() progresses it
822*1c60b9acSAndroid Build Coastguard Worker * asynchronously.
823*1c60b9acSAndroid Build Coastguard Worker */
824*1c60b9acSAndroid Build Coastguard Worker
825*1c60b9acSAndroid Build Coastguard Worker m = 0;
826*1c60b9acSAndroid Build Coastguard Worker while (!force_exit) {
827*1c60b9acSAndroid Build Coastguard Worker
828*1c60b9acSAndroid Build Coastguard Worker if (do_multi) {
829*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)LWS_ARRAY_SIZE(wsi_multi); n++) {
830*1c60b9acSAndroid Build Coastguard Worker if (!wsi_multi[n] && ratelimit_connects(&rl_multi[n], 2u)) {
831*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("dumb %d: connecting\n", n);
832*1c60b9acSAndroid Build Coastguard Worker i.protocol = protocols[PROTOCOL_DUMB_INCREMENT].name;
833*1c60b9acSAndroid Build Coastguard Worker i.pwsi = &wsi_multi[n];
834*1c60b9acSAndroid Build Coastguard Worker lws_client_connect_via_info(&i);
835*1c60b9acSAndroid Build Coastguard Worker }
836*1c60b9acSAndroid Build Coastguard Worker }
837*1c60b9acSAndroid Build Coastguard Worker } else {
838*1c60b9acSAndroid Build Coastguard Worker
839*1c60b9acSAndroid Build Coastguard Worker if (do_ws) {
840*1c60b9acSAndroid Build Coastguard Worker if (!flag_echo && !justmirror && !wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) {
841*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("dumb: connecting\n");
842*1c60b9acSAndroid Build Coastguard Worker i.protocol = protocols[PROTOCOL_DUMB_INCREMENT].name;
843*1c60b9acSAndroid Build Coastguard Worker i.pwsi = &wsi_dumb;
844*1c60b9acSAndroid Build Coastguard Worker lws_client_connect_via_info(&i);
845*1c60b9acSAndroid Build Coastguard Worker }
846*1c60b9acSAndroid Build Coastguard Worker
847*1c60b9acSAndroid Build Coastguard Worker if (!wsi_mirror && ratelimit_connects(&rl_mirror, 2u)) {
848*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("mirror: connecting\n");
849*1c60b9acSAndroid Build Coastguard Worker i.protocol = protocols[PROTOCOL_LWS_MIRROR].name;
850*1c60b9acSAndroid Build Coastguard Worker i.pwsi = &wsi_mirror;
851*1c60b9acSAndroid Build Coastguard Worker wsi_mirror = lws_client_connect_via_info(&i);
852*1c60b9acSAndroid Build Coastguard Worker }
853*1c60b9acSAndroid Build Coastguard Worker } else
854*1c60b9acSAndroid Build Coastguard Worker if (!wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) {
855*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("http: connecting\n");
856*1c60b9acSAndroid Build Coastguard Worker i.pwsi = &wsi_dumb;
857*1c60b9acSAndroid Build Coastguard Worker lws_client_connect_via_info(&i);
858*1c60b9acSAndroid Build Coastguard Worker }
859*1c60b9acSAndroid Build Coastguard Worker }
860*1c60b9acSAndroid Build Coastguard Worker
861*1c60b9acSAndroid Build Coastguard Worker lws_service(context, 500);
862*1c60b9acSAndroid Build Coastguard Worker
863*1c60b9acSAndroid Build Coastguard Worker if (do_multi) {
864*1c60b9acSAndroid Build Coastguard Worker m++;
865*1c60b9acSAndroid Build Coastguard Worker if (m == 10) {
866*1c60b9acSAndroid Build Coastguard Worker m = 0;
867*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("doing lws_callback_on_writable_all_protocol\n");
868*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable_all_protocol(context,
869*1c60b9acSAndroid Build Coastguard Worker &protocols[PROTOCOL_DUMB_INCREMENT]);
870*1c60b9acSAndroid Build Coastguard Worker }
871*1c60b9acSAndroid Build Coastguard Worker }
872*1c60b9acSAndroid Build Coastguard Worker
873*1c60b9acSAndroid Build Coastguard Worker if (flag_echo && lws_now_secs() != last) {
874*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("rxb %d, rx_count %d\n", rxb, rx_count);
875*1c60b9acSAndroid Build Coastguard Worker last = lws_now_secs();
876*1c60b9acSAndroid Build Coastguard Worker }
877*1c60b9acSAndroid Build Coastguard Worker }
878*1c60b9acSAndroid Build Coastguard Worker
879*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Exiting\n");
880*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(context);
881*1c60b9acSAndroid Build Coastguard Worker
882*1c60b9acSAndroid Build Coastguard Worker return ret;
883*1c60b9acSAndroid Build Coastguard Worker
884*1c60b9acSAndroid Build Coastguard Worker usage:
885*1c60b9acSAndroid Build Coastguard Worker fprintf(stderr, "Usage: libwebsockets-test-client "
886*1c60b9acSAndroid Build Coastguard Worker "<server address> [--port=<p>] "
887*1c60b9acSAndroid Build Coastguard Worker "[--ssl] [-k] [-v <ver>] "
888*1c60b9acSAndroid Build Coastguard Worker "[-d <log bitfield>] [-l]\n");
889*1c60b9acSAndroid Build Coastguard Worker return 1;
890*1c60b9acSAndroid Build Coastguard Worker }
891