mirror-protocol-chrome-and-firefox.patch
[profile/ivi/libwebsockets.git] / test-server / test-server.c
1 /*
2  * libwebsockets-test-server - libwebsockets test implementation
3  * 
4  * Copyright (C) 2010 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 #include "../lib/libwebsockets.h"
29
30 /*
31  * This demo server shows how to use libwebsockets for one or more
32  * websocket protocols in the same server
33  *
34  * It defines the following websocket protocols:
35  *
36  *  dumb-increment-protocol:  once the socket is opened, an incrementing
37  *                              ascii string is sent down it every 50ms.
38  *                              If you send "reset\n" on the websocket, then
39  *                              the incrementing number is reset to 0.
40  *
41  *  lws-mirror-protocol: copies any received packet to every connection also
42  *                              using this protocol, including the sender
43  */
44
45
46 #define LOCAL_RESOURCE_PATH "/usr/share/libwebsockets-test-server"
47 static int port = 7681;
48 static int use_ssl = 0;
49
50 /* this protocol server (always the first one) just knows how to do HTTP */
51
52 static int callback_http(struct libwebsocket * wsi,
53                 enum libwebsocket_callback_reasons reason, void * user,
54                                                            void *in, size_t len)
55 {
56         switch (reason) {
57         case LWS_CALLBACK_HTTP:
58                 fprintf(stderr, "serving HTTP URI %s\n", in);
59                 
60                 if (in && strcmp(in, "/favicon.ico") == 0) {
61                         if (libwebsockets_serve_http_file(wsi,
62                              LOCAL_RESOURCE_PATH"/favicon.ico", "image/x-icon"))
63                                 fprintf(stderr, "Failed to send favicon\n");
64                         break;
65                 }
66                 
67                 /* send the script... when it runs it'll start websockets */
68
69                 if (libwebsockets_serve_http_file(wsi,
70                                   LOCAL_RESOURCE_PATH"/test.html", "text/html"))
71                         fprintf(stderr, "Failed to send HTTP file\n");
72                 break;
73
74         default:
75                 break;
76         }
77
78         return 0;
79 }
80
81 /* dumb_increment protocol */
82
83 struct per_session_data__dumb_increment {
84         int number;
85 };
86
87 static int
88 callback_dumb_increment(struct libwebsocket * wsi,
89                         enum libwebsocket_callback_reasons reason,
90                         void * user, void *in, size_t len)
91 {
92         int n;
93         char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
94                                                   LWS_SEND_BUFFER_POST_PADDING];
95         unsigned char *p = (unsigned char *)&buf[LWS_SEND_BUFFER_PRE_PADDING];
96         struct per_session_data__dumb_increment * pss = user;
97         
98         switch (reason) {
99
100         case LWS_CALLBACK_ESTABLISHED:
101                 pss->number = 0;
102                 break;
103
104         case LWS_CALLBACK_SEND: 
105                 n = sprintf(p, "%d", pss->number++);
106                 n = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
107                 if (n < 0) {
108                         fprintf(stderr, "ERROR writing to socket");
109                         return 1;
110                 }
111                 break;
112
113         case LWS_CALLBACK_RECEIVE:
114                 fprintf(stderr, "rx %d\n", len);
115                 if (len < 6)
116                         break;
117                 if (strcmp(in, "reset\n") == 0)
118                         pss->number = 0;
119                 break;
120
121         default:
122                 break;
123         }
124
125         return 0;
126 }
127
128
129 /* lws-mirror_protocol */
130
131 #define MAX_MESSAGE_QUEUE 64
132
133 struct per_session_data__lws_mirror {
134         struct libwebsocket * wsi;
135         int ringbuffer_tail;
136 };
137
138 struct a_message {
139         void * payload;
140         size_t len;
141 };
142
143 static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
144 static int ringbuffer_head;
145
146
147 static int
148 callback_lws_mirror(struct libwebsocket * wsi,
149                         enum libwebsocket_callback_reasons reason,
150                         void * user, void *in, size_t len)
151 {
152         int n;
153         char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
154                                                   LWS_SEND_BUFFER_POST_PADDING];
155         unsigned char *p = (unsigned char *)&buf[LWS_SEND_BUFFER_PRE_PADDING];
156         struct per_session_data__lws_mirror * pss = user;
157         
158         switch (reason) {
159
160         case LWS_CALLBACK_ESTABLISHED:
161                 pss->wsi = wsi;
162                 pss->ringbuffer_tail = ringbuffer_head;
163                 break;
164
165         case LWS_CALLBACK_SEND: 
166                 /* send everything that's pending */
167                 while (pss->ringbuffer_tail != ringbuffer_head) {
168
169                         n = libwebsocket_write(wsi,
170                                 (unsigned char *)ringbuffer[pss->ringbuffer_tail].payload +
171                                         LWS_SEND_BUFFER_PRE_PADDING,
172                                    ringbuffer[pss->ringbuffer_tail].len,
173                                                         LWS_WRITE_TEXT);
174                         if (n < 0) {
175                                 fprintf(stderr, "ERROR writing to socket");
176                                 exit(1);
177                         }
178
179                         if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
180                                 pss->ringbuffer_tail = 0;
181                         else
182                                 pss->ringbuffer_tail++;
183                 }
184                 break;
185
186         case LWS_CALLBACK_RECEIVE:
187                 if (ringbuffer[ringbuffer_head].payload)
188                         free(ringbuffer[ringbuffer_head].payload );
189
190                 ringbuffer[ringbuffer_head].payload =
191                                 malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
192                                                   LWS_SEND_BUFFER_POST_PADDING);
193                 ringbuffer[ringbuffer_head].len = len;
194                 memcpy(ringbuffer[ringbuffer_head].payload +
195                                           LWS_SEND_BUFFER_PRE_PADDING, in, len);
196                 if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
197                         ringbuffer_head = 0;
198                 else
199                         ringbuffer_head++;
200                 break;
201
202         default:
203                 break;
204         }
205
206         return 0;
207 }
208
209
210 /* list of supported protocols and callbacks */
211
212 static const struct libwebsocket_protocols protocols[] = {
213         {
214                 .name = "http-only",
215                 .callback = callback_http,
216                 .per_session_data_size = 0,
217         },
218         {
219                 .name = "dumb-increment-protocol",
220                 .callback = callback_dumb_increment,
221                 .per_session_data_size =
222                                 sizeof(struct per_session_data__dumb_increment),
223         },
224         {
225                 .name = "lws-mirror-protocol",
226                 .callback = callback_lws_mirror,
227                 .per_session_data_size =
228                                 sizeof(struct per_session_data__lws_mirror),
229         },
230         {  /* end of list */
231                 .callback = NULL
232         }
233 };
234
235 static struct option options[] = {
236         { "help",       no_argument, NULL, 'h' },
237         { "port",       required_argument, NULL, 'p' },
238         { "ssl",        no_argument, NULL, 's' },
239         { NULL, 0, 0, 0 }
240 };
241
242 int main(int argc, char **argv)
243 {
244         int n = 0;
245         const char * cert_path =
246                             LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
247         const char * key_path =
248                         LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
249
250         fprintf(stderr, "libwebsockets test server\n"
251                         "(C) Copyright 2010 Andy Green <andy@warmcat.com> "
252                                                     "licensed under LGPL2.1\n");
253         
254         while (n >= 0) {
255                 n = getopt_long(argc, argv, "hp:", options, NULL);
256                 if (n < 0)
257                         continue;
258                 switch (n) {
259                 case 's':
260                         use_ssl = 1;
261                         break;
262                 case 'p':
263                         port = atoi(optarg);
264                         break;
265                 case 'h':
266                         fprintf(stderr, "Usage: test-server "
267                                              "[--port=<p>] [--ssl]\n");
268                         exit(1);
269                 }
270         }
271
272         if (!use_ssl)
273                 cert_path = key_path = NULL;
274         
275         if (libwebsocket_create_server(port, protocols,
276                                        cert_path, key_path, -1, -1) < 0) {
277                 fprintf(stderr, "libwebsocket init failed\n");
278                 return -1;
279         }
280
281         return 0;
282 }