clean--fix-sigpipe.patch
[platform/upstream/libwebsockets.git] / test-server / test-client.c
1 /*
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
45 enum 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
57 static int
58 callback_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
80 struct coord {
81         int x;
82         int y;
83 };
84
85 static 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
211 static int
212 callback_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
232 static 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
247 static 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
255 int 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         libwebsocket_context_destroy(context);
384
385         return 0;
386
387 usage:
388         fprintf(stderr, "Usage: libwebsockets-test-client "
389                                              "<server address> [--port=<p>] "
390                                              "[--ssl]\n");
391         return 1;
392 }