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