introduce listen on specific interface
[profile/ivi/libwebsockets.git] / test-server / test-server.c
1 /*
2  * libwebsockets-test-server - libwebsockets test implementation
3  *
4  * Copyright (C) 2010-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 #include <sys/time.h>
28
29 #include "../lib/libwebsockets.h"
30
31
32 /*
33  * This demo server shows how to use libwebsockets for one or more
34  * websocket protocols in the same server
35  *
36  * It defines the following websocket protocols:
37  *
38  *  dumb-increment-protocol:  once the socket is opened, an incrementing
39  *                              ascii string is sent down it every 50ms.
40  *                              If you send "reset\n" on the websocket, then
41  *                              the incrementing number is reset to 0.
42  *
43  *  lws-mirror-protocol: copies any received packet to every connection also
44  *                              using this protocol, including the sender
45  */
46
47 enum demo_protocols {
48         /* always first */
49         PROTOCOL_HTTP = 0,
50
51         PROTOCOL_DUMB_INCREMENT,
52         PROTOCOL_LWS_MIRROR,
53
54         /* always last */
55         DEMO_PROTOCOL_COUNT
56 };
57
58
59 #define LOCAL_RESOURCE_PATH DATADIR"/libwebsockets-test-server"
60
61 /* this protocol server (always the first one) just knows how to do HTTP */
62
63 static int callback_http(struct libwebsocket_context * this,
64                 struct libwebsocket *wsi,
65                 enum libwebsocket_callback_reasons reason, void *user,
66                                                            void *in, size_t len)
67 {
68         char client_name[128];
69         char client_ip[128];
70
71         switch (reason) {
72         case LWS_CALLBACK_HTTP:
73                 fprintf(stderr, "serving HTTP URI %s\n", (char *)in);
74
75                 if (in && strcmp(in, "/favicon.ico") == 0) {
76                         if (libwebsockets_serve_http_file(wsi,
77                              LOCAL_RESOURCE_PATH"/favicon.ico", "image/x-icon"))
78                                 fprintf(stderr, "Failed to send favicon\n");
79                         break;
80                 }
81
82                 /* send the script... when it runs it'll start websockets */
83
84                 if (libwebsockets_serve_http_file(wsi,
85                                   LOCAL_RESOURCE_PATH"/test.html", "text/html"))
86                         fprintf(stderr, "Failed to send HTTP file\n");
87                 break;
88
89         /*
90          * callback for confirming to continue with client IP appear in
91          * protocol 0 callback since no websocket protocol has been agreed
92          * yet.  You can just ignore this if you won't filter on client IP
93          * since the default uhandled callback return is 0 meaning let the
94          * connection continue.
95          */
96
97         case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
98
99                 libwebsockets_get_peer_addresses((int)(long)user, client_name,
100                              sizeof(client_name), client_ip, sizeof(client_ip));
101
102                 fprintf(stderr, "Received network connect from %s (%s)\n",
103                                                         client_name, client_ip);
104
105                 /* if we returned non-zero from here, we kill the connection */
106                 break;
107
108         default:
109                 break;
110         }
111
112         return 0;
113 }
114
115
116 /*
117  * this is just an example of parsing handshake headers, you don't need this
118  * in your code unless you will filter allowing connections by the header
119  * content
120  */
121
122 static void
123 dump_handshake_info(struct lws_tokens *lwst)
124 {
125         int n;
126         static const char *token_names[] = {
127                 [WSI_TOKEN_GET_URI] = "GET URI",
128                 [WSI_TOKEN_HOST] = "Host",
129                 [WSI_TOKEN_CONNECTION] = "Connection",
130                 [WSI_TOKEN_KEY1] = "key 1",
131                 [WSI_TOKEN_KEY2] = "key 2",
132                 [WSI_TOKEN_PROTOCOL] = "Protocol",
133                 [WSI_TOKEN_UPGRADE] = "Upgrade",
134                 [WSI_TOKEN_ORIGIN] = "Origin",
135                 [WSI_TOKEN_DRAFT] = "Draft",
136                 [WSI_TOKEN_CHALLENGE] = "Challenge",
137
138                 /* new for 04 */
139                 [WSI_TOKEN_KEY] = "Key",
140                 [WSI_TOKEN_VERSION] = "Version",
141                 [WSI_TOKEN_SWORIGIN] = "Sworigin",
142
143                 /* new for 05 */
144                 [WSI_TOKEN_EXTENSIONS] = "Extensions",
145
146                 /* client receives these */
147                 [WSI_TOKEN_ACCEPT] = "Accept",
148                 [WSI_TOKEN_NONCE] = "Nonce",
149                 [WSI_TOKEN_HTTP] = "Http",
150         };
151         
152         for (n = 0; n < WSI_TOKEN_COUNT; n++) {
153                 if (lwst[n].token == NULL)
154                         continue;
155
156                 fprintf(stderr, "    %s = %s\n", token_names[n], lwst[n].token);
157         }
158 }
159
160 /* dumb_increment protocol */
161
162 /*
163  * one of these is auto-created for each connection and a pointer to the
164  * appropriate instance is passed to the callback in the user parameter
165  *
166  * for this example protocol we use it to individualize the count for each
167  * connection.
168  */
169
170 struct per_session_data__dumb_increment {
171         int number;
172 };
173
174 static int
175 callback_dumb_increment(struct libwebsocket_context * this,
176                         struct libwebsocket *wsi,
177                         enum libwebsocket_callback_reasons reason,
178                                                void *user, void *in, size_t len)
179 {
180         int n;
181         unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
182                                                   LWS_SEND_BUFFER_POST_PADDING];
183         unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
184         struct per_session_data__dumb_increment *pss = user;
185
186         switch (reason) {
187
188         case LWS_CALLBACK_ESTABLISHED:
189                 pss->number = 0;
190                 break;
191
192         /*
193          * in this protocol, we just use the broadcast action as the chance to
194          * send our own connection-specific data and ignore the broadcast info
195          * that is available in the 'in' parameter
196          */
197
198         case LWS_CALLBACK_BROADCAST:
199                 n = sprintf((char *)p, "%d", pss->number++);
200                 n = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
201                 if (n < 0) {
202                         fprintf(stderr, "ERROR writing to socket");
203                         return 1;
204                 }
205                 break;
206
207         case LWS_CALLBACK_RECEIVE:
208                 fprintf(stderr, "rx %d\n", (int)len);
209                 if (len < 6)
210                         break;
211                 if (strcmp(in, "reset\n") == 0)
212                         pss->number = 0;
213                 break;
214         /*
215          * this just demonstrates how to use the protocol filter. If you won't
216          * study and reject connections based on header content, you don't need
217          * to handle this callback
218          */
219
220         case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
221                 dump_handshake_info((struct lws_tokens *)(long)user);
222                 /* you could return non-zero here and kill the connection */
223                 break;
224
225         default:
226                 break;
227         }
228
229         return 0;
230 }
231
232
233 /* lws-mirror_protocol */
234
235 #define MAX_MESSAGE_QUEUE 64
236
237 struct per_session_data__lws_mirror {
238         struct libwebsocket *wsi;
239         int ringbuffer_tail;
240 };
241
242 struct a_message {
243         void *payload;
244         size_t len;
245 };
246
247 static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
248 static int ringbuffer_head;
249
250
251 static int
252 callback_lws_mirror(struct libwebsocket_context * this,
253                         struct libwebsocket *wsi,
254                         enum libwebsocket_callback_reasons reason,
255                                                void *user, void *in, size_t len)
256 {
257         int n;
258         struct per_session_data__lws_mirror *pss = user;
259
260         switch (reason) {
261
262         case LWS_CALLBACK_ESTABLISHED:
263                 pss->ringbuffer_tail = ringbuffer_head;
264                 pss->wsi = wsi;
265                 break;
266
267         case LWS_CALLBACK_CLIENT_WRITEABLE:
268                 if (pss->ringbuffer_tail != ringbuffer_head) {
269
270                         n = libwebsocket_write(wsi, (unsigned char *)
271                                    ringbuffer[pss->ringbuffer_tail].payload +
272                                    LWS_SEND_BUFFER_PRE_PADDING,
273                                    ringbuffer[pss->ringbuffer_tail].len,
274                                                                 LWS_WRITE_TEXT);
275                         if (n < 0) {
276                                 fprintf(stderr, "ERROR writing to socket");
277                                 exit(1);
278                         }
279
280                         if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
281                                 pss->ringbuffer_tail = 0;
282                         else
283                                 pss->ringbuffer_tail++;
284
285                         if (((ringbuffer_head - pss->ringbuffer_tail) %
286                                   MAX_MESSAGE_QUEUE) < (MAX_MESSAGE_QUEUE - 15))
287                                 libwebsocket_rx_flow_control(wsi, 1);
288
289                         libwebsocket_callback_on_writable(this, wsi);
290
291                 }
292                 break;
293
294         case LWS_CALLBACK_BROADCAST:
295                 n = libwebsocket_write(wsi, in, len, LWS_WRITE_TEXT);
296                 if (n < 0)
297                         fprintf(stderr, "mirror write failed\n");
298                 break;
299
300         case LWS_CALLBACK_RECEIVE:
301
302                 if (ringbuffer[ringbuffer_head].payload)
303                         free(ringbuffer[ringbuffer_head].payload);
304
305                 ringbuffer[ringbuffer_head].payload =
306                                 malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
307                                                   LWS_SEND_BUFFER_POST_PADDING);
308                 ringbuffer[ringbuffer_head].len = len;
309                 memcpy((char *)ringbuffer[ringbuffer_head].payload +
310                                           LWS_SEND_BUFFER_PRE_PADDING, in, len);
311                 if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
312                         ringbuffer_head = 0;
313                 else
314                         ringbuffer_head++;
315
316                 if (((ringbuffer_head - pss->ringbuffer_tail) %
317                                   MAX_MESSAGE_QUEUE) > (MAX_MESSAGE_QUEUE - 10))
318                         libwebsocket_rx_flow_control(wsi, 0);
319
320                 libwebsocket_callback_on_writable_all_protocol(
321                                                libwebsockets_get_protocol(wsi));
322                 break;
323         /*
324          * this just demonstrates how to use the protocol filter. If you won't
325          * study and reject connections based on header content, you don't need
326          * to handle this callback
327          */
328
329         case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
330                 dump_handshake_info((struct lws_tokens *)(long)user);
331                 /* you could return non-zero here and kill the connection */
332                 break;
333
334         default:
335                 break;
336         }
337
338         return 0;
339 }
340
341
342 /* list of supported protocols and callbacks */
343
344 static struct libwebsocket_protocols protocols[] = {
345         /* first protocol must always be HTTP handler */
346         [PROTOCOL_HTTP] = {
347                 .name = "http-only",
348                 .callback = callback_http,
349         },
350         [PROTOCOL_DUMB_INCREMENT] = {
351                 .name = "dumb-increment-protocol",
352                 .callback = callback_dumb_increment,
353                 .per_session_data_size =
354                                 sizeof(struct per_session_data__dumb_increment),
355         },
356         [PROTOCOL_LWS_MIRROR] = {
357                 .name = "lws-mirror-protocol",
358                 .callback = callback_lws_mirror,
359                 .per_session_data_size =
360                                 sizeof(struct per_session_data__lws_mirror),
361         },
362         [DEMO_PROTOCOL_COUNT] = {  /* end of list */
363                 .callback = NULL
364         }
365 };
366
367 static struct option options[] = {
368         { "help",       no_argument,            NULL, 'h' },
369         { "port",       required_argument,      NULL, 'p' },
370         { "ssl",        no_argument,            NULL, 's' },
371         { "killmask",   no_argument,            NULL, 'k' },
372         { "interface",  required_argument,      NULL, 'i' },
373         { NULL, 0, 0, 0 }
374 };
375
376 int main(int argc, char **argv)
377 {
378         int n = 0;
379         const char *cert_path =
380                             LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
381         const char *key_path =
382                         LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
383         unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1024 +
384                                                   LWS_SEND_BUFFER_POST_PADDING];
385         int port = 7681;
386         int use_ssl = 0;
387         struct libwebsocket_context *context;
388         int opts = 0;
389         char interface_name[128] = "";
390         const char * interface = NULL;
391 #ifdef LWS_NO_FORK
392         unsigned int oldus = 0;
393 #endif
394
395         fprintf(stderr, "libwebsockets test server\n"
396                         "(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> "
397                                                     "licensed under LGPL2.1\n");
398
399         while (n >= 0) {
400                 n = getopt_long(argc, argv, "i:khsp:", options, NULL);
401                 if (n < 0)
402                         continue;
403                 switch (n) {
404                 case 's':
405                         use_ssl = 1;
406                         break;
407                 case 'k':
408                         opts = LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK;
409                         break;
410                 case 'p':
411                         port = atoi(optarg);
412                         break;
413                 case 'i':
414                         strncpy(interface_name, optarg, sizeof interface_name);
415                         interface_name[(sizeof interface_name) - 1] = '\0';
416                         interface = interface_name;
417                         break;
418                 case 'h':
419                         fprintf(stderr, "Usage: test-server "
420                                              "[--port=<p>] [--ssl]\n");
421                         exit(1);
422                 }
423         }
424
425         if (!use_ssl)
426                 cert_path = key_path = NULL;
427
428         context = libwebsocket_create_context(port, interface, protocols,
429                                 cert_path, key_path, -1, -1, opts);
430         if (context == NULL) {
431                 fprintf(stderr, "libwebsocket init failed\n");
432                 return -1;
433         }
434
435         buf[LWS_SEND_BUFFER_PRE_PADDING] = 'x';
436
437 #ifdef LWS_NO_FORK
438
439         /*
440          * This example shows how to work with no forked service loop
441          */
442
443         fprintf(stderr, " Using no-fork service loop\n");
444
445         while (1) {
446                 struct timeval tv;
447
448                 gettimeofday(&tv, NULL);
449
450                 /*
451                  * This broadcasts to all dumb-increment-protocol connections
452                  * at 20Hz.
453                  *
454                  * We're just sending a character 'x', in these examples the
455                  * callbacks send their own per-connection content.
456                  *
457                  * You have to send something with nonzero length to get the
458                  * callback actions delivered.
459                  *
460                  * We take care of pre-and-post padding allocation.
461                  */
462
463                 if (((unsigned int)tv.tv_usec - oldus) > 50000) {
464                         libwebsockets_broadcast(
465                                         &protocols[PROTOCOL_DUMB_INCREMENT],
466                                         &buf[LWS_SEND_BUFFER_PRE_PADDING], 1);
467                         oldus = tv.tv_usec;
468                 }
469
470                 /*
471                  * This example server does not fork or create a thread for
472                  * websocket service, it all runs in this single loop.  So,
473                  * we have to give the websockets an opportunity to service
474                  * "manually".
475                  *
476                  * If no socket is needing service, the call below returns
477                  * immediately and quickly.
478                  */
479
480                 libwebsocket_service(context, 50);
481         }
482
483 #else
484
485         /*
486          * This example shows how to work with the forked websocket service loop
487          */
488
489         fprintf(stderr, " Using forked service loop\n");
490
491         /*
492          * This forks the websocket service action into a subprocess so we
493          * don't have to take care about it.
494          */
495
496         n = libwebsockets_fork_service_loop(context);
497         if (n < 0) {
498                 fprintf(stderr, "Unable to fork service loop %d\n", n);
499                 return 1;
500         }
501
502         while (1) {
503
504                 usleep(50000);
505
506                 /*
507                  * This broadcasts to all dumb-increment-protocol connections
508                  * at 20Hz.
509                  *
510                  * We're just sending a character 'x', in these examples the
511                  * callbacks send their own per-connection content.
512                  *
513                  * You have to send something with nonzero length to get the
514                  * callback actions delivered.
515                  *
516                  * We take care of pre-and-post padding allocation.
517                  */
518
519                 libwebsockets_broadcast(&protocols[PROTOCOL_DUMB_INCREMENT],
520                                         &buf[LWS_SEND_BUFFER_PRE_PADDING], 1);
521         }
522
523 #endif
524
525         libwebsocket_context_destroy(context);
526
527         return 0;
528 }