blob: 6869d6dc1c300f6dd9acea77f5275f4652f4b12c [file] [log] [blame]
Andy Green4739e5c2011-01-22 12:51:57 +00001/*
2 * libwebsockets-test-client - libwebsockets test implementation
3 *
4 * Copyright (C) 2011 Andy Green <andy@warmcat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <getopt.h>
26#include <string.h>
27
28
29#include "../lib/libwebsockets.h"
30#include <poll.h>
31
32/*
33 * This demo shows how to connect multiple websockets simultaneously to a
34 * websocket server (there is no restriction on their having to be the same
35 * server just it simplifies the demo).
36 *
37 * dumb-increment-protocol: we connect to the server and print the number
38 * we are given
39 *
40 * lws-mirror-protocol: draws random circles, which are mirrored on to every
41 * client (see them being drawn in every browser
42 * session also using the test server)
43 */
44
45enum demo_protocols {
46
47 PROTOCOL_DUMB_INCREMENT,
48 PROTOCOL_LWS_MIRROR,
49
50 /* always last */
51 DEMO_PROTOCOL_COUNT
52};
53
54
55/* dumb_increment protocol */
56
57static int
58callback_dumb_increment(struct libwebsocket *wsi,
59 enum libwebsocket_callback_reasons reason,
60 void *user, void *in, size_t len)
61{
62 switch (reason) {
63
64 case LWS_CALLBACK_CLIENT_RECEIVE:
65 fprintf(stderr, "rx %d '%s'\n", len, in);
66 break;
67
68 default:
69 break;
70 }
71
72 return 0;
73}
74
75
76/* lws-mirror_protocol */
77
78/* "how to draw a circle" */
79
80struct coord {
81 int x;
82 int y;
83};
84
85static struct coord circle[] = {
86
87{ 0, 240 },
88{ 12, 239 },
89{ 25, 238 },
90{ 37, 237 },
91{ 49, 234 },
92{ 62, 231 },
93{ 74, 228 },
94{ 86, 224 },
95{ 97, 219 },
96{ 108, 213 },
97{ 120, 207 },
98{ 130, 201 },
99{ 141, 194 },
100{ 151, 186 },
101{ 160, 178 },
102{ 169, 169 },
103{ 178, 160 },
104{ 186, 151 },
105{ 194, 141 },
106{ 201, 130 },
107{ 207, 120 },
108{ 213, 108 },
109{ 219, 97 },
110{ 224, 86 },
111{ 228, 74 },
112{ 231, 62 },
113{ 234, 49 },
114{ 237, 37 },
115{ 238, 25 },
116{ 239, 12 },
117{ 240, 0 },
118{ 239, -12 },
119{ 238, -25 },
120{ 237, -37 },
121{ 234, -49 },
122{ 231, -62 },
123{ 228, -74 },
124{ 224, -86 },
125{ 219, -97 },
126{ 213, -108 },
127{ 207, -120 },
128{ 201, -130 },
129{ 194, -141 },
130{ 186, -151 },
131{ 178, -160 },
132{ 169, -169 },
133{ 160, -178 },
134{ 151, -186 },
135{ 141, -194 },
136{ 130, -201 },
137{ 120, -207 },
138{ 108, -213 },
139{ 97, -219 },
140{ 86, -224 },
141{ 74, -228 },
142{ 62, -231 },
143{ 49, -234 },
144{ 37, -237 },
145{ 25, -238 },
146{ 12, -239 },
147{ 0, -240 },
148{ -12, -239 },
149{ -25, -238 },
150{ -37, -237 },
151{ -49, -234 },
152{ -62, -231 },
153{ -74, -228 },
154{ -86, -224 },
155{ -97, -219 },
156{ -108, -213 },
157{ -119, -207 },
158{ -130, -201 },
159{ -141, -194 },
160{ -151, -186 },
161{ -160, -178 },
162{ -169, -169 },
163{ -178, -160 },
164{ -186, -151 },
165{ -194, -141 },
166{ -201, -130 },
167{ -207, -120 },
168{ -213, -108 },
169{ -219, -97 },
170{ -224, -86 },
171{ -228, -74 },
172{ -231, -62 },
173{ -234, -49 },
174{ -237, -37 },
175{ -238, -25 },
176{ -239, -12 },
177{ -240, 0 },
178{ -239, 12 },
179{ -238, 25 },
180{ -237, 37 },
181{ -234, 49 },
182{ -231, 62 },
183{ -228, 74 },
184{ -224, 86 },
185{ -219, 97 },
186{ -213, 108 },
187{ -207, 120 },
188{ -201, 130 },
189{ -194, 141 },
190{ -186, 151 },
191{ -178, 160 },
192{ -169, 169 },
193{ -160, 178 },
194{ -151, 186 },
195{ -141, 194 },
196{ -130, 201 },
197{ -119, 207 },
198{ -108, 213 },
199{ -97, 219 },
200{ -86, 224 },
201{ -74, 228 },
202{ -62, 231 },
203{ -49, 234 },
204{ -37, 237 },
205{ -25, 238 },
206{ -12, 239 },
207{ 0, 240 },
208
209};
210
211static int
212callback_lws_mirror(struct libwebsocket *wsi,
213 enum libwebsocket_callback_reasons reason,
214 void *user, void *in, size_t len)
215{
216 switch (reason) {
217
218 case LWS_CALLBACK_CLIENT_RECEIVE:
219// fprintf(stderr, "rx %d '%s'\n", len, in);
220 break;
221
222 default:
223 break;
224 }
225
226 return 0;
227}
228
229
230/* list of supported protocols and callbacks */
231
232static struct libwebsocket_protocols protocols[] = {
233
234 [PROTOCOL_DUMB_INCREMENT] = {
235 .name = "dumb-increment-protocol",
236 .callback = callback_dumb_increment,
237 },
238 [PROTOCOL_LWS_MIRROR] = {
239 .name = "lws-mirror-protocol",
240 .callback = callback_lws_mirror,
241 },
242 [DEMO_PROTOCOL_COUNT] = { /* end of list */
243 .callback = NULL
244 }
245};
246
247static struct option options[] = {
248 { "help", no_argument, NULL, 'h' },
249 { "port", required_argument, NULL, 'p' },
250 { "ssl", no_argument, NULL, 's' },
251 { NULL, 0, 0, 0 }
252};
253
254
255int main(int argc, char **argv)
256{
257 int n = 0;
258 int port = 7681;
259 int use_ssl = 0;
260 struct libwebsocket_context *context;
261 const char * address = argv[1];
262 struct libwebsocket *wsi_dumb;
263 struct libwebsocket *wsi_mirror;
264 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1024 +
265 LWS_SEND_BUFFER_POST_PADDING];
266 int len;
267 int i = 0;
268 int xofs;
269 int yofs;
270 int oldx;
271 int oldy;
272 int scale;
273 int colour;
274
275 fprintf(stderr, "libwebsockets test client\n"
276 "(C) Copyright 2010 Andy Green <andy@warmcat.com> "
277 "licensed under LGPL2.1\n");
278
279 if (argc < 2)
280 goto usage;
281
282 optind++;
283
284 while (n >= 0) {
285 n = getopt_long(argc, argv, "hsp:", options, NULL);
286 if (n < 0)
287 continue;
288 switch (n) {
289 case 's':
290 use_ssl = 1;
291 break;
292 case 'p':
293 port = atoi(optarg);
294 break;
295 case 'h':
296 goto usage;
297 }
298 }
299
300 /*
301 * create the websockets context. This tracks open connections and
302 * knows how to route any traffic and which protocol version to use,
303 * and if each connection is client or server side.
304 *
305 * For this client-only demo, we tell it to not listen on any port.
306 */
307
308 context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN,
309 protocols, NULL, NULL, -1, -1);
310 if (context == NULL) {
311 fprintf(stderr, "Creating libwebsocket context failed\n");
312 return 1;
313 }
314
315
316 /* create a client websocket using dumb increment protocol */
317
318 wsi_dumb = libwebsocket_client_connect(context, address, port, "/",
319 "http://host", "origin",
320 protocols[PROTOCOL_DUMB_INCREMENT].name);
321
322 if (wsi_dumb == NULL) {
323 fprintf(stderr, "libwebsocket dumb connect failed\n");
324 return -1;
325 }
326
327 /* create a client websocket using mirror protocol */
328
329 wsi_mirror = libwebsocket_client_connect(context, address, port, "/",
330 "http://host", "origin",
331 protocols[PROTOCOL_LWS_MIRROR].name);
332
333 if (wsi_mirror == NULL) {
334 fprintf(stderr, "libwebsocket dumb connect failed\n");
335 return -1;
336 }
337
338 fprintf(stderr, "Websocket connections opened\n");
339
340 /*
341 * sit there servicing the websocket context to handle incoming
342 * packets, and drawing random circles on the mirror protocol websocket
343 */
344
345 n = 0;
346 while (n >= 0) {
347
348 usleep(10000);
349
350 if (i == sizeof circle / sizeof circle[0])
351 i = 0;
352
353 if (i == 0) {
354 xofs = random() % 500;
355 yofs = random() % 250;
356 scale = random() % 24;
357 if (!scale)
358 scale = 1;
359
360 oldx = xofs + (circle[i].x / scale);
361 oldy = yofs + (circle[i].y / scale);
362 colour = random() & 0xffffff;
363 }
364
365 len = sprintf(&buf[LWS_SEND_BUFFER_PRE_PADDING],
366 "d #%06X %d %d %d %d", colour, oldx, oldy,
367 xofs + (circle[i].x / scale),
368 yofs + (circle[i].y / scale));
369 oldx = xofs + (circle[i].x / scale);
370 oldy = yofs + (circle[i].y / scale);
371 i++;
372
373 libwebsocket_write(wsi_mirror,
374 &buf[LWS_SEND_BUFFER_PRE_PADDING], len, LWS_WRITE_TEXT);
375
376
377 n = libwebsocket_service(context, 0);
378 }
379
380 libwebsocket_client_close(wsi_dumb);
381 libwebsocket_client_close(wsi_mirror);
382
383 return 0;
384
385usage:
386 fprintf(stderr, "Usage: libwebsockets-test-client "
387 "<server address> [--port=<p>] "
388 "[--ssl]\n");
389 return 1;
390}