blob: 1ba4410d020945c8ad36a92d2af5a93696b5c709 [file] [log] [blame]
Andy Green05a0a7b2010-10-31 17:51:39 +00001/*
Andy Greena0da8a82010-11-08 17:12:19 +00002 * libwebsockets - small server side websockets and web server implementation
Andy Green8f037e42010-12-19 22:13:26 +00003 *
Andy Greena0da8a82010-11-08 17:12:19 +00004 * 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
Andy Green05a0a7b2010-10-31 17:51:39 +000020 */
21
Andy Green7c212cc2010-11-08 20:20:42 +000022#include "private-libwebsockets.h"
Andy Greenff95d7a2010-10-28 22:36:01 +010023
Andy Green3faa9c72010-11-08 17:03:03 +000024#ifdef LWS_OPENSSL_SUPPORT
Andy Green3faa9c72010-11-08 17:03:03 +000025SSL_CTX *ssl_ctx;
26int use_ssl;
27#endif
28
Andy Green8f037e42010-12-19 22:13:26 +000029void
Andy Green251f6fa2010-11-03 11:13:06 +000030libwebsocket_close_and_free_session(struct libwebsocket *wsi)
31{
Andy Greenb45993c2010-12-18 15:13:50 +000032 int n;
33
34 if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
35 return;
36
37 n = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +000038
39 wsi->state = WSI_STATE_DEAD_SOCKET;
40
Andy Green4f3943a2010-11-12 10:44:16 +000041 if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED)
Andy Greene77ddd82010-11-13 10:03:47 +000042 wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED,
43 wsi->user_space, NULL, 0);
Andy Green251f6fa2010-11-03 11:13:06 +000044
45 for (n = 0; n < WSI_TOKEN_COUNT; n++)
46 if (wsi->utf8_token[n].token)
47 free(wsi->utf8_token[n].token);
48
Andy Green0ca6a172010-12-19 20:50:01 +000049/* fprintf(stderr, "closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +000050
Andy Green3faa9c72010-11-08 17:03:03 +000051#ifdef LWS_OPENSSL_SUPPORT
52 if (use_ssl) {
53 n = SSL_get_fd(wsi->ssl);
54 SSL_shutdown(wsi->ssl);
55 close(n);
56 SSL_free(wsi->ssl);
57 } else {
58#endif
59 shutdown(wsi->sock, SHUT_RDWR);
60 close(wsi->sock);
61#ifdef LWS_OPENSSL_SUPPORT
62 }
63#endif
Andy Green4f3943a2010-11-12 10:44:16 +000064 if (wsi->user_space)
65 free(wsi->user_space);
66
Andy Green251f6fa2010-11-03 11:13:06 +000067 free(wsi);
68}
69
Andy Greenb45993c2010-12-18 15:13:50 +000070static int
71libwebsocket_poll_connections(struct libwebsocket_context *this)
72{
73 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BROADCAST_PAYLOAD +
74 LWS_SEND_BUFFER_POST_PADDING];
Andy Green8f037e42010-12-19 22:13:26 +000075 int client = this->count_protocols + 1;
76 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +000077 int n;
78 size_t len;
79
80 /* check for activity on client sockets */
Andy Green8f037e42010-12-19 22:13:26 +000081
82 for (; client < this->fds_count; client++) {
83
Andy Greenb45993c2010-12-18 15:13:50 +000084 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +000085
Andy Greenb45993c2010-12-18 15:13:50 +000086 if (this->fds[client].revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +000087
Andy Greenb45993c2010-12-18 15:13:50 +000088 debug("Session Socket %d %p (fd=%d) dead\n",
89 client, this->wsi[client], this->fds[client]);
90
91 libwebsocket_close_and_free_session(this->wsi[client]);
92 goto nuke_this;
93 }
Andy Green8f037e42010-12-19 22:13:26 +000094
Andy Greenb45993c2010-12-18 15:13:50 +000095 /* any incoming data ready? */
96
97 if (!(this->fds[client].revents & POLLIN))
98 continue;
99
100 /* broadcast? */
101
102 if ((unsigned long)this->wsi[client] < LWS_MAX_PROTOCOLS) {
103
Andy Green8f037e42010-12-19 22:13:26 +0000104 /* get the issued broadcast payload from the socket */
105
Andy Greenb45993c2010-12-18 15:13:50 +0000106 len = read(this->fds[client].fd,
107 buf + LWS_SEND_BUFFER_PRE_PADDING,
108 MAX_BROADCAST_PAYLOAD);
Andy Green8f037e42010-12-19 22:13:26 +0000109
Andy Greenb45993c2010-12-18 15:13:50 +0000110 if (len < 0) {
Andy Green8f037e42010-12-19 22:13:26 +0000111 fprintf(stderr,
112 "Error reading broadcast payload\n");
Andy Greenb45993c2010-12-18 15:13:50 +0000113 continue;
114 }
115
116 /* broadcast it to all guys with this protocol index */
117
118 for (n = this->count_protocols + 1;
119 n < this->fds_count; n++) {
120
Andy Green8f037e42010-12-19 22:13:26 +0000121 wsi = this->wsi[n];
122
123 if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
Andy Greenb45993c2010-12-18 15:13:50 +0000124 continue;
125
126 /*
127 * never broadcast to non-established
128 * connection
129 */
130
Andy Green8f037e42010-12-19 22:13:26 +0000131 if (wsi->state != WSI_STATE_ESTABLISHED)
Andy Greenb45993c2010-12-18 15:13:50 +0000132 continue;
133
134 /*
135 * only broadcast to connections using
136 * the requested protocol
137 */
138
Andy Green8f037e42010-12-19 22:13:26 +0000139 if (wsi->protocol->protocol_index !=
140 (int)(unsigned long)this->wsi[client])
Andy Greenb45993c2010-12-18 15:13:50 +0000141 continue;
142
Andy Green8f037e42010-12-19 22:13:26 +0000143 /* broadcast it to this connection */
144
145 wsi->protocol->callback(wsi,
146 LWS_CALLBACK_BROADCAST,
147 wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +0000148 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +0000149 }
150
151 continue;
152 }
153
154#ifdef LWS_OPENSSL_SUPPORT
155 if (this->use_ssl)
156 n = SSL_read(this->wsi[client]->ssl, buf, sizeof buf);
157 else
158#endif
159 n = recv(this->fds[client].fd, buf, sizeof buf, 0);
160
161 if (n < 0) {
162 fprintf(stderr, "Socket read returned %d\n", n);
163 continue;
164 }
165 if (!n) {
Andy Green8f037e42010-12-19 22:13:26 +0000166 libwebsocket_close_and_free_session(this->wsi[client]);
Andy Greenb45993c2010-12-18 15:13:50 +0000167 goto nuke_this;
168 }
169
Andy Greenb45993c2010-12-18 15:13:50 +0000170 /* service incoming data */
171
172 if (libwebsocket_read(this->wsi[client], buf, n) >= 0)
173 continue;
Andy Green8f037e42010-12-19 22:13:26 +0000174
Andy Greenb45993c2010-12-18 15:13:50 +0000175 /*
176 * it closed and nuked wsi[client], so remove the
177 * socket handle and wsi from our service list
178 */
179nuke_this:
180
181 debug("nuking wsi %p, fsd_count = %d\n",
182 this->wsi[client], this->fds_count - 1);
183
184 this->fds_count--;
185 for (n = client; n < this->fds_count; n++) {
186 this->fds[n] = this->fds[n + 1];
187 this->wsi[n] = this->wsi[n + 1];
188 }
189 break;
190 }
191
192 return 0;
193}
194
195
Andy Greene92cd172011-01-19 13:11:55 +0000196int
197libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
198{
199 int n;
200 int client;
201 unsigned int clilen;
202 struct sockaddr_in cli_addr;
203 int fd;
204
205 /* stay dead once we are dead */
206
207 if (this == NULL)
208 return 1;
209
210 n = poll(this->fds, this->fds_count, timeout_ms);
211
212 if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
213 fprintf(stderr, "Listen Socket dead\n");
214 goto fatal;
215 }
216 if (n == 0) /* poll timeout */
217 return 0;
218
219 /* handle accept on listening socket? */
220
221 for (client = 0; client < this->count_protocols + 1; client++) {
222
223 if (!this->fds[client].revents & POLLIN)
224 continue;
225
226 /* listen socket got an unencrypted connection... */
227
228 clilen = sizeof(cli_addr);
229 fd = accept(this->fds[client].fd,
230 (struct sockaddr *)&cli_addr, &clilen);
231 if (fd < 0) {
232 fprintf(stderr, "ERROR on accept");
233 continue;
234 }
235
236 if (this->fds_count >= MAX_CLIENTS) {
237 fprintf(stderr, "too busy");
238 close(fd);
239 continue;
240 }
241
242 if (client) {
243 /*
244 * accepting a connection to broadcast socket
245 * set wsi to be protocol index not pointer
246 */
247
248 this->wsi[this->fds_count] =
249 (struct libwebsocket *)(long)(client - 1);
250
251 goto fill_in_fds;
252 }
253
254 /* accepting connection to main listener */
255
256 this->wsi[this->fds_count] =
257 malloc(sizeof(struct libwebsocket));
258 if (!this->wsi[this->fds_count]) {
259 fprintf(stderr, "Out of memory for new connection\n");
260 continue;
261 }
262
263#ifdef LWS_OPENSSL_SUPPORT
264 if (this->use_ssl) {
265
266 this->wsi[this->fds_count]->ssl = SSL_new(ssl_ctx);
267 if (this->wsi[this->fds_count]->ssl == NULL) {
268 fprintf(stderr, "SSL_new failed: %s\n",
269 ERR_error_string(SSL_get_error(
270 this->wsi[this->fds_count]->ssl, 0),
271 NULL));
272 free(this->wsi[this->fds_count]);
273 continue;
274 }
275
276 SSL_set_fd(this->wsi[this->fds_count]->ssl, fd);
277
278 n = SSL_accept(this->wsi[this->fds_count]->ssl);
279 if (n != 1) {
280 /*
281 * browsers seem to probe with various
282 * ssl params which fail then retry
283 * and succeed
284 */
285 debug("SSL_accept failed skt %u: %s\n",
286 fd,
287 ERR_error_string(SSL_get_error(
288 this->wsi[this->fds_count]->ssl,
289 n), NULL));
290 SSL_free(
291 this->wsi[this->fds_count]->ssl);
292 free(this->wsi[this->fds_count]);
293 continue;
294 }
295 debug("accepted new SSL conn "
296 "port %u on fd=%d SSL ver %s\n",
297 ntohs(cli_addr.sin_port), fd,
298 SSL_get_version(this->wsi[
299 this->fds_count]->ssl));
300
301 } else
302#endif
303 debug("accepted new conn port %u on fd=%d\n",
304 ntohs(cli_addr.sin_port), fd);
305
306 /* intialize the instance struct */
307
308 this->wsi[this->fds_count]->sock = fd;
309 this->wsi[this->fds_count]->state = WSI_STATE_HTTP;
310 this->wsi[this->fds_count]->name_buffer_pos = 0;
311
312 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
313 this->wsi[this->fds_count]->
314 utf8_token[n].token = NULL;
315 this->wsi[this->fds_count]->
316 utf8_token[n].token_len = 0;
317 }
318
319 /*
320 * these can only be set once the protocol is known
321 * we set an unestablished connection's protocol pointer
322 * to the start of the supported list, so it can look
323 * for matching ones during the handshake
324 */
325 this->wsi[this->fds_count]->protocol = this->protocols;
326 this->wsi[this->fds_count]->user_space = NULL;
327
328 /*
329 * Default protocol is 76 / 00
330 * After 76, there's a header specified to inform which
331 * draft the client wants, when that's seen we modify
332 * the individual connection's spec revision accordingly
333 */
334 this->wsi[this->fds_count]->ietf_spec_revision = 0;
335
336fill_in_fds:
337
338 /*
339 * make sure NO events are seen yet on this new socket
340 * (otherwise we inherit old fds[client].revents from
341 * previous socket there and die mysteriously! )
342 */
343 this->fds[this->fds_count].revents = 0;
344
345 this->fds[this->fds_count].events = POLLIN;
346 this->fds[this->fds_count++].fd = fd;
347
348 }
349
350 /* service anything incoming on websocket connection */
351
352 libwebsocket_poll_connections(this);
353
354 /* this round is done */
355
356 return 0;
357
358fatal:
359
360 /* close listening skt and per-protocol broadcast sockets */
361 for (client = 0; client < this->fds_count; client++)
362 close(this->fds[0].fd);
363
364#ifdef LWS_OPENSSL_SUPPORT
365 SSL_CTX_free(ssl_ctx);
366#endif
367 kill(0, SIGTERM);
368
369 if (this)
370 free(this);
371
372 this = NULL;
373
374 /* inform caller we are dead */
375
376 return 1;
377}
378
Andy Greenb45993c2010-12-18 15:13:50 +0000379
Andy Greenab990e42010-10-31 12:42:52 +0000380/**
381 * libwebsocket_create_server() - Create the listening websockets server
382 * @port: Port to listen on
Andy Green4f3943a2010-11-12 10:44:16 +0000383 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +0000384 * specific callback for each one. The list is ended with an
385 * entry that has a NULL callback pointer.
386 * It's not const because we write the owning_server member
Andy Green3faa9c72010-11-08 17:03:03 +0000387 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +0000388 * to listen using SSL, set to the filepath to fetch the
389 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +0000390 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +0000391 * else ignored
Andy Green3faa9c72010-11-08 17:03:03 +0000392 * @gid: group id to change to after setting listen socket, or -1.
393 * @uid: user id to change to after setting listen socket, or -1.
Andy Green05464c62010-11-12 10:44:18 +0000394 *
Andy Green8f037e42010-12-19 22:13:26 +0000395 * This function creates the listening socket and takes care
396 * of all initialization in one step.
397 *
Andy Greene92cd172011-01-19 13:11:55 +0000398 * After initialization, it returns a struct libwebsocket_context * that
399 * represents this server. After calling, user code needs to take care
400 * of calling libwebsocket_service() with the context pointer to get the
401 * server's sockets serviced. This can be done in the same process context
402 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +0000403 *
Andy Green8f037e42010-12-19 22:13:26 +0000404 * The protocol callback functions are called for a handful of events
405 * including http requests coming in, websocket connections becoming
406 * established, and data arriving; it's also called periodically to allow
407 * async transmission.
408 *
409 * HTTP requests are sent always to the FIRST protocol in @protocol, since
410 * at that time websocket protocol has not been negotiated. Other
411 * protocols after the first one never see any HTTP callack activity.
412 *
413 * The server created is a simple http server by default; part of the
414 * websocket standard is upgrading this http connection to a websocket one.
415 *
416 * This allows the same server to provide files like scripts and favicon /
417 * images or whatever over http and dynamic data over websockets all in
418 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +0000419 */
Andy Green4ea60062010-10-30 12:15:07 +0100420
Andy Greene92cd172011-01-19 13:11:55 +0000421struct libwebsocket_context *
422libwebsocket_create_server(int port,
Andy Greenb45993c2010-12-18 15:13:50 +0000423 struct libwebsocket_protocols *protocols,
Andy Green8f037e42010-12-19 22:13:26 +0000424 const char *ssl_cert_filepath,
425 const char *ssl_private_key_filepath,
Andy Greence510c62010-11-11 12:48:13 +0000426 int gid, int uid)
Andy Greenff95d7a2010-10-28 22:36:01 +0100427{
428 int n;
Andy Green69fa0722010-11-03 08:25:13 +0000429 int sockfd;
Andy Green251f6fa2010-11-03 11:13:06 +0000430 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +0100431 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +0000432 int opt = 1;
Andy Green8f037e42010-12-19 22:13:26 +0000433 struct libwebsocket_context *this = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000434 unsigned int slen;
Andy Greenff95d7a2010-10-28 22:36:01 +0100435
Andy Green3faa9c72010-11-08 17:03:03 +0000436#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +0000437 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +0000438 char ssl_err_buf[512];
439
440 use_ssl = ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL;
441 if (use_ssl)
442 fprintf(stderr, " Compiled with SSL support, using it\n");
443 else
Andy Green018d8eb2010-11-08 21:04:23 +0000444 fprintf(stderr, " Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +0000445
446#else
447 if (ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL) {
448 fprintf(stderr, " Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +0000449 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000450 }
Andy Green018d8eb2010-11-08 21:04:23 +0000451 fprintf(stderr, " Compiled without SSL support, serving unencrypted\n");
Andy Green3faa9c72010-11-08 17:03:03 +0000452#endif
453
454#ifdef LWS_OPENSSL_SUPPORT
455 if (use_ssl) {
456 SSL_library_init();
457
458 OpenSSL_add_all_algorithms();
459 SSL_load_error_strings();
460
Andy Green0ca6a172010-12-19 20:50:01 +0000461 /*
462 * Firefox insists on SSLv23 not SSLv3
463 * Konq disables SSLv2 by default now, SSLv23 works
464 */
Andy Green3faa9c72010-11-08 17:03:03 +0000465
Andy Greenb45993c2010-12-18 15:13:50 +0000466 method = (SSL_METHOD *)SSLv23_server_method();
Andy Green3faa9c72010-11-08 17:03:03 +0000467 if (!method) {
468 fprintf(stderr, "problem creating ssl method: %s\n",
469 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000470 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000471 }
472 ssl_ctx = SSL_CTX_new(method); /* create context */
473 if (!ssl_ctx) {
474 printf("problem creating ssl context: %s\n",
475 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000476 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000477 }
478 /* set the local certificate from CertFile */
479 n = SSL_CTX_use_certificate_file(ssl_ctx,
480 ssl_cert_filepath, SSL_FILETYPE_PEM);
481 if (n != 1) {
482 fprintf(stderr, "problem getting cert '%s': %s\n",
483 ssl_cert_filepath,
484 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000485 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000486 }
487 /* set the private key from KeyFile */
Andy Green018d8eb2010-11-08 21:04:23 +0000488 if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
489 ssl_private_key_filepath,
490 SSL_FILETYPE_PEM) != 1) {
491 fprintf(stderr, "ssl problem getting key '%s': %s\n",
492 ssl_private_key_filepath,
493 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000494 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000495 }
496 /* verify private key */
497 if (!SSL_CTX_check_private_key(ssl_ctx)) {
Andy Green018d8eb2010-11-08 21:04:23 +0000498 fprintf(stderr, "Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +0000499 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000500 }
501
502 /* SSL is happy and has a cert it's content with */
503 }
504#endif
Andy Greenb45993c2010-12-18 15:13:50 +0000505
Andy Greendf736162011-01-18 15:39:02 +0000506 /* selftest */
507
508 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +0000509 return NULL;
Andy Greendf736162011-01-18 15:39:02 +0000510
511
Andy Green8f037e42010-12-19 22:13:26 +0000512 this = malloc(sizeof(struct libwebsocket_context));
Andy Greenb45993c2010-12-18 15:13:50 +0000513
Andy Greene92cd172011-01-19 13:11:55 +0000514 this->protocols = protocols;
515
Andy Greenb45993c2010-12-18 15:13:50 +0000516 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +0000517
Andy Green775c0dd2010-10-29 14:15:22 +0100518 sockfd = socket(AF_INET, SOCK_STREAM, 0);
519 if (sockfd < 0) {
520 fprintf(stderr, "ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +0000521 return NULL;
Andy Green775c0dd2010-10-29 14:15:22 +0100522 }
Andy Green8f037e42010-12-19 22:13:26 +0000523
Andy Green251f6fa2010-11-03 11:13:06 +0000524 /* allow us to restart even if old sockets in TIME_WAIT */
525 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
Andy Green775c0dd2010-10-29 14:15:22 +0100526
Andy Green251f6fa2010-11-03 11:13:06 +0000527 bzero((char *) &serv_addr, sizeof(serv_addr));
Andy Green775c0dd2010-10-29 14:15:22 +0100528 serv_addr.sin_family = AF_INET;
529 serv_addr.sin_addr.s_addr = INADDR_ANY;
530 serv_addr.sin_port = htons(port);
Andy Greene77ddd82010-11-13 10:03:47 +0000531
Andy Green775c0dd2010-10-29 14:15:22 +0100532 n = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
533 if (n < 0) {
Andy Green8f037e42010-12-19 22:13:26 +0000534 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
535 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +0000536 return NULL;
Andy Green8f037e42010-12-19 22:13:26 +0000537 }
Andy Greenb45993c2010-12-18 15:13:50 +0000538
Andy Greene77ddd82010-11-13 10:03:47 +0000539 /* drop any root privs for this process */
Andy Green3faa9c72010-11-08 17:03:03 +0000540
541 if (gid != -1)
542 if (setgid(gid))
543 fprintf(stderr, "setgid: %s\n", strerror(errno));
544 if (uid != -1)
545 if (setuid(uid))
546 fprintf(stderr, "setuid: %s\n", strerror(errno));
547
Andy Green8f037e42010-12-19 22:13:26 +0000548 /*
Andy Greenb45993c2010-12-18 15:13:50 +0000549 * prepare the poll() fd array... it's like this
550 *
551 * [0] = external listening socket
552 * [1 .. this->count_protocols] = per-protocol broadcast sockets
553 * [this->count_protocols + 1 ... this->fds_count-1] = connection skts
Andy Green4f3943a2010-11-12 10:44:16 +0000554 */
555
Andy Greenb45993c2010-12-18 15:13:50 +0000556 this->fds_count = 1;
557 this->fds[0].fd = sockfd;
558 this->fds[0].events = POLLIN;
559 this->count_protocols = 0;
560#ifdef LWS_OPENSSL_SUPPORT
561 this->use_ssl = use_ssl;
562#endif
563
Andy Greenff95d7a2010-10-28 22:36:01 +0100564 listen(sockfd, 5);
Andy Green251f6fa2010-11-03 11:13:06 +0000565 fprintf(stderr, " Listening on port %d\n", port);
Andy Greenb45993c2010-12-18 15:13:50 +0000566
567 /* set up our internal broadcast trigger sockets per-protocol */
568
569 for (; protocols[this->count_protocols].callback;
570 this->count_protocols++) {
571 protocols[this->count_protocols].owning_server = this;
572 protocols[this->count_protocols].protocol_index =
573 this->count_protocols;
574
575 fd = socket(AF_INET, SOCK_STREAM, 0);
576 if (fd < 0) {
577 fprintf(stderr, "ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +0000578 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000579 }
Andy Green8f037e42010-12-19 22:13:26 +0000580
Andy Greenb45993c2010-12-18 15:13:50 +0000581 /* allow us to restart even if old sockets in TIME_WAIT */
582 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
583
584 bzero((char *) &serv_addr, sizeof(serv_addr));
585 serv_addr.sin_family = AF_INET;
586 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
587 serv_addr.sin_port = 0; /* pick the port for us */
588
589 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
590 if (n < 0) {
Andy Green8f037e42010-12-19 22:13:26 +0000591 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +0000592 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +0000593 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000594 }
595
596 slen = sizeof cli_addr;
597 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
598 if (n < 0) {
599 fprintf(stderr, "getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +0000600 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000601 }
602 protocols[this->count_protocols].broadcast_socket_port =
603 ntohs(cli_addr.sin_port);
604 listen(fd, 5);
605
606 debug(" Protocol %s broadcast socket %d\n",
607 protocols[this->count_protocols].name,
608 ntohs(cli_addr.sin_port));
609
610 this->fds[this->fds_count].fd = fd;
611 this->fds[this->fds_count].events = POLLIN;
612 /* wsi only exists for connections, not broadcast listener */
613 this->wsi[this->fds_count] = NULL;
614 this->fds_count++;
615 }
616
Andy Greene92cd172011-01-19 13:11:55 +0000617 return this;
618}
Andy Greenb45993c2010-12-18 15:13:50 +0000619
Andy Greene92cd172011-01-19 13:11:55 +0000620/**
621 * libwebsockets_fork_service_loop() - Optional helper function forks off
622 * a process for the websocket server loop.
623 * You don't have to use this but if not, you
624 * have to make sure you are calling
625 * libwebsocket_service periodically to service
626 * the websocket traffic
627 * @this: server context returned by creation function
628 */
Andy Greenb45993c2010-12-18 15:13:50 +0000629
Andy Greene92cd172011-01-19 13:11:55 +0000630int
631libwebsockets_fork_service_loop(struct libwebsocket_context *this)
632{
633 int client;
634 int fd;
635 struct sockaddr_in cli_addr;
636 int n;
Andy Greenb45993c2010-12-18 15:13:50 +0000637
Andy Greene92cd172011-01-19 13:11:55 +0000638 if (fork())
639 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +0000640
Andy Greene92cd172011-01-19 13:11:55 +0000641 for (client = 1; client < this->count_protocols + 1; client++) {
642 fd = socket(AF_INET, SOCK_STREAM, 0);
643 if (fd < 0) {
644 fprintf(stderr, "Unable to create socket\n");
645 return -1;
646 }
647 cli_addr.sin_family = AF_INET;
648 cli_addr.sin_port = htons(
649 this->protocols[client - 1].broadcast_socket_port);
650 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
651 n = connect(fd, (struct sockaddr *)&cli_addr,
652 sizeof cli_addr);
653 if (n < 0) {
654 fprintf(stderr, "Unable to connect to "
655 "broadcast socket %d, %s\n",
656 client, strerror(errno));
657 return -1;
Andy Greenb45993c2010-12-18 15:13:50 +0000658 }
659
Andy Greene92cd172011-01-19 13:11:55 +0000660 this->protocols[client - 1].broadcast_socket_user_fd = fd;
Andy Greenb45993c2010-12-18 15:13:50 +0000661 }
662
663 /* we want a SIGHUP when our parent goes down */
664 prctl(PR_SET_PDEATHSIG, SIGHUP);
665
666 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +0000667
Andy Greene92cd172011-01-19 13:11:55 +0000668 while (1)
669 if (libwebsocket_service(this, 1000))
670 return -1;
Andy Green8f037e42010-12-19 22:13:26 +0000671
Andy Green251f6fa2010-11-03 11:13:06 +0000672 return 0;
Andy Greenff95d7a2010-10-28 22:36:01 +0100673}
674
Andy Greenb45993c2010-12-18 15:13:50 +0000675/**
676 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +0000677 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +0000678 * @wsi: pointer to struct websocket you want to know the protocol of
679 *
Andy Green8f037e42010-12-19 22:13:26 +0000680 *
681 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +0000682 * the callback.
683 */
Andy Greenab990e42010-10-31 12:42:52 +0000684
Andy Greenb45993c2010-12-18 15:13:50 +0000685const struct libwebsocket_protocols *
686libwebsockets_get_protocol(struct libwebsocket *wsi)
687{
688 return wsi->protocol;
689}
690
691/**
Andy Greene92cd172011-01-19 13:11:55 +0000692 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +0000693 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +0000694 * @protocol: pointer to the protocol you will broadcast to all members of
695 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +0000696 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
697 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
698 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +0000699 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +0000700 *
701 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +0000702 * the given protocol. It does not send the data directly; instead it calls
703 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
704 * wants to actually send the data for that connection, the callback itself
705 * should call libwebsocket_write().
706 *
707 * libwebsockets_broadcast() can be called from another fork context without
708 * having to take any care about data visibility between the processes, it'll
709 * "just work".
710 */
711
712
713int
Andy Green8f037e42010-12-19 22:13:26 +0000714libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +0000715 unsigned char *buf, size_t len)
716{
Andy Green8f037e42010-12-19 22:13:26 +0000717 struct libwebsocket_context *this = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +0000718 int n;
719
720 if (!protocol->broadcast_socket_user_fd) {
721 /*
Andy Greene92cd172011-01-19 13:11:55 +0000722 * We are either running unforked / flat, or we are being
723 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +0000724 * eg, from a callback. In that case don't use sockets for
725 * broadcast IPC (since we can't open a socket connection to
726 * a socket listening on our own thread) but directly do the
727 * send action.
728 *
729 * Locking is not needed because we are by definition being
730 * called in the poll thread context and are serialized.
731 */
732
733 for (n = this->count_protocols + 1; n < this->fds_count; n++) {
734
735 if ((unsigned long)this->wsi[n] < LWS_MAX_PROTOCOLS)
736 continue;
737
738 /* never broadcast to non-established connection */
739
740 if (this->wsi[n]->state != WSI_STATE_ESTABLISHED)
741 continue;
742
743 /* only broadcast to guys using requested protocol */
744
745 if (this->wsi[n]->protocol != protocol)
746 continue;
747
Andy Green8f037e42010-12-19 22:13:26 +0000748 this->wsi[n]->protocol->callback(this->wsi[n],
749 LWS_CALLBACK_BROADCAST,
Andy Greenb45993c2010-12-18 15:13:50 +0000750 this->wsi[n]->user_space,
751 buf, len);
752 }
753
754 return 0;
755 }
756
Andy Green0ca6a172010-12-19 20:50:01 +0000757 /*
758 * We're being called from a different process context than the server
759 * loop. Instead of broadcasting directly, we send our
760 * payload on a socket to do the IPC; the server process will serialize
761 * the broadcast action in its main poll() loop.
762 *
763 * There's one broadcast socket listening for each protocol supported
764 * set up when the websocket server initializes
765 */
766
Andy Greenb45993c2010-12-18 15:13:50 +0000767 n = send(protocol->broadcast_socket_user_fd, buf, len, 0);
768
769 return n;
770}