1 /*
2 * lws-minimal-ws-client-echo
3 *
4 * Written in 2010-2019 by Andy Green <andy@warmcat.com>
5 *
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
8 *
9 * This demonstrates a ws client that echoes back what it was sent, in a
10 * way compatible with autobahn -m fuzzingserver
11 */
12
13 #include <libwebsockets.h>
14 #include <string.h>
15 #include <signal.h>
16
17 #define LWS_PLUGIN_STATIC
18 #include "protocol_lws_minimal_client_echo.c"
19
20 static struct lws_protocols protocols[] = {
21 LWS_PLUGIN_PROTOCOL_MINIMAL_CLIENT_ECHO,
22 LWS_PROTOCOL_LIST_TERM
23 };
24
25 static struct lws_context *context;
26 static int interrupted, port = 7681, options = 0;
27 static const char *url = "/", *ads = "localhost", *iface = NULL;
28
29 /* pass pointers to shared vars to the protocol */
30
31 static const struct lws_protocol_vhost_options pvo_iface = {
32 NULL,
33 NULL,
34 "iface", /* pvo name */
35 (void *)&iface /* pvo value */
36 };
37
38 static const struct lws_protocol_vhost_options pvo_ads = {
39 &pvo_iface,
40 NULL,
41 "ads", /* pvo name */
42 (void *)&ads /* pvo value */
43 };
44
45 static const struct lws_protocol_vhost_options pvo_url = {
46 &pvo_ads,
47 NULL,
48 "url", /* pvo name */
49 (void *)&url /* pvo value */
50 };
51
52 static const struct lws_protocol_vhost_options pvo_options = {
53 &pvo_url,
54 NULL,
55 "options", /* pvo name */
56 (void *)&options /* pvo value */
57 };
58
59 static const struct lws_protocol_vhost_options pvo_port = {
60 &pvo_options,
61 NULL,
62 "port", /* pvo name */
63 (void *)&port /* pvo value */
64 };
65
66 static const struct lws_protocol_vhost_options pvo_interrupted = {
67 &pvo_port,
68 NULL,
69 "interrupted", /* pvo name */
70 (void *)&interrupted /* pvo value */
71 };
72
73 static const struct lws_protocol_vhost_options pvo = {
74 NULL, /* "next" pvo linked-list */
75 &pvo_interrupted, /* "child" pvo linked-list */
76 "lws-minimal-client-echo", /* protocol name we belong to on this vhost */
77 "" /* ignored */
78 };
79 static const struct lws_extension extensions[] = {
80 {
81 "permessage-deflate",
82 lws_extension_callback_pm_deflate,
83 "permessage-deflate"
84 "; client_no_context_takeover"
85 "; client_max_window_bits"
86 },
87 { NULL, NULL, NULL /* terminator */ }
88 };
89
sigint_handler(int sig)90 void sigint_handler(int sig)
91 {
92 interrupted = 1;
93 }
94
main(int argc,const char ** argv)95 int main(int argc, const char **argv)
96 {
97 struct lws_context_creation_info info;
98 const char *p;
99 int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
100 /* for LLL_ verbosity above NOTICE to be built into lws,
101 * lws must have been configured and built with
102 * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
103 /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
104 /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
105 /* | LLL_DEBUG */;
106
107 if ((p = lws_cmdline_option(argc, argv, "-d")))
108 logs = atoi(p);
109
110 lws_set_log_level(logs, NULL);
111 lwsl_user("LWS minimal ws client echo + permessage-deflate + multifragment bulk message\n");
112 lwsl_user(" lws-minimal-ws-client-echo [-n (no exts)] [-u url] [-p port] [-o (once)]\n");
113
114 if ((p = lws_cmdline_option(argc, argv, "-u")))
115 url = p;
116
117 if ((p = lws_cmdline_option(argc, argv, "-p")))
118 port = atoi(p);
119
120 if (lws_cmdline_option(argc, argv, "-o"))
121 options |= 1;
122
123 if (lws_cmdline_option(argc, argv, "--ssl"))
124 options |= 2;
125
126 if ((p = lws_cmdline_option(argc, argv, "-s")))
127 ads = p;
128
129 if ((p = lws_cmdline_option(argc, argv, "-i")))
130 iface = p;
131
132 lwsl_user("options %d, ads %s\n", options, ads);
133
134 memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
135 info.port = CONTEXT_PORT_NO_LISTEN;
136 info.protocols = protocols;
137 info.pvo = &pvo;
138 if (!lws_cmdline_option(argc, argv, "-n"))
139 info.extensions = extensions;
140 info.pt_serv_buf_size = 32 * 1024;
141 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
142 LWS_SERVER_OPTION_VALIDATE_UTF8;
143 /*
144 * since we know this lws context is only ever going to be used with
145 * one client wsis / fds / sockets at a time, let lws know it doesn't
146 * have to use the default allocations for fd tables up to ulimit -n.
147 * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
148 * will use.
149 */
150 info.fd_limit_per_thread = 1 + 1 + 1;
151
152 if (lws_cmdline_option(argc, argv, "--libuv"))
153 info.options |= LWS_SERVER_OPTION_LIBUV;
154 else
155 signal(SIGINT, sigint_handler);
156
157 context = lws_create_context(&info);
158 if (!context) {
159 lwsl_err("lws init failed\n");
160 return 1;
161 }
162
163 while (!lws_service(context, 0) && !interrupted)
164 ;
165
166 lws_context_destroy(context);
167
168 n = (options & 1) ? interrupted != 2 : interrupted == 3;
169 lwsl_user("Completed %d %s\n", interrupted, !n ? "OK" : "failed");
170
171 return n;
172 }
173