blob: aae66908c44983c9bae38092d3c314ea9b1b1c5c [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
Andy Green4739e5c2011-01-22 12:51:57 +0000134 /* only to clients connected to us */
135
136 if (wsi->client_mode)
137 continue;
138
Andy Greenb45993c2010-12-18 15:13:50 +0000139 /*
140 * only broadcast to connections using
141 * the requested protocol
142 */
143
Andy Green8f037e42010-12-19 22:13:26 +0000144 if (wsi->protocol->protocol_index !=
145 (int)(unsigned long)this->wsi[client])
Andy Greenb45993c2010-12-18 15:13:50 +0000146 continue;
147
Andy Green8f037e42010-12-19 22:13:26 +0000148 /* broadcast it to this connection */
149
150 wsi->protocol->callback(wsi,
151 LWS_CALLBACK_BROADCAST,
152 wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +0000153 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +0000154 }
155
156 continue;
157 }
158
159#ifdef LWS_OPENSSL_SUPPORT
160 if (this->use_ssl)
161 n = SSL_read(this->wsi[client]->ssl, buf, sizeof buf);
162 else
163#endif
164 n = recv(this->fds[client].fd, buf, sizeof buf, 0);
165
166 if (n < 0) {
167 fprintf(stderr, "Socket read returned %d\n", n);
168 continue;
169 }
170 if (!n) {
Andy Green8f037e42010-12-19 22:13:26 +0000171 libwebsocket_close_and_free_session(this->wsi[client]);
Andy Greenb45993c2010-12-18 15:13:50 +0000172 goto nuke_this;
173 }
174
Andy Greenb45993c2010-12-18 15:13:50 +0000175 /* service incoming data */
176
177 if (libwebsocket_read(this->wsi[client], buf, n) >= 0)
178 continue;
Andy Green8f037e42010-12-19 22:13:26 +0000179
Andy Greenb45993c2010-12-18 15:13:50 +0000180 /*
181 * it closed and nuked wsi[client], so remove the
182 * socket handle and wsi from our service list
183 */
184nuke_this:
185
186 debug("nuking wsi %p, fsd_count = %d\n",
187 this->wsi[client], this->fds_count - 1);
188
189 this->fds_count--;
190 for (n = client; n < this->fds_count; n++) {
191 this->fds[n] = this->fds[n + 1];
192 this->wsi[n] = this->wsi[n + 1];
193 }
194 break;
195 }
196
197 return 0;
198}
199
200
Andy Greene92cd172011-01-19 13:11:55 +0000201int
202libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
203{
204 int n;
205 int client;
206 unsigned int clilen;
207 struct sockaddr_in cli_addr;
208 int fd;
209
210 /* stay dead once we are dead */
211
212 if (this == NULL)
213 return 1;
214
Andy Green4739e5c2011-01-22 12:51:57 +0000215 /* don't check listen socket if we are not listening */
216
217 if (this->listen_port)
218 n = poll(this->fds, this->fds_count, timeout_ms);
219 else
220 n = poll(&this->fds[1], this->fds_count - 1, timeout_ms);
221
Andy Greene92cd172011-01-19 13:11:55 +0000222
223 if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
224 fprintf(stderr, "Listen Socket dead\n");
225 goto fatal;
226 }
227 if (n == 0) /* poll timeout */
228 return 0;
229
230 /* handle accept on listening socket? */
231
232 for (client = 0; client < this->count_protocols + 1; client++) {
233
234 if (!this->fds[client].revents & POLLIN)
235 continue;
236
237 /* listen socket got an unencrypted connection... */
238
239 clilen = sizeof(cli_addr);
240 fd = accept(this->fds[client].fd,
241 (struct sockaddr *)&cli_addr, &clilen);
242 if (fd < 0) {
243 fprintf(stderr, "ERROR on accept");
244 continue;
245 }
246
247 if (this->fds_count >= MAX_CLIENTS) {
248 fprintf(stderr, "too busy");
249 close(fd);
250 continue;
251 }
252
253 if (client) {
254 /*
255 * accepting a connection to broadcast socket
256 * set wsi to be protocol index not pointer
257 */
258
259 this->wsi[this->fds_count] =
260 (struct libwebsocket *)(long)(client - 1);
261
262 goto fill_in_fds;
263 }
264
265 /* accepting connection to main listener */
266
267 this->wsi[this->fds_count] =
268 malloc(sizeof(struct libwebsocket));
269 if (!this->wsi[this->fds_count]) {
270 fprintf(stderr, "Out of memory for new connection\n");
271 continue;
272 }
273
274#ifdef LWS_OPENSSL_SUPPORT
275 if (this->use_ssl) {
276
277 this->wsi[this->fds_count]->ssl = SSL_new(ssl_ctx);
278 if (this->wsi[this->fds_count]->ssl == NULL) {
279 fprintf(stderr, "SSL_new failed: %s\n",
280 ERR_error_string(SSL_get_error(
281 this->wsi[this->fds_count]->ssl, 0),
282 NULL));
283 free(this->wsi[this->fds_count]);
284 continue;
285 }
286
287 SSL_set_fd(this->wsi[this->fds_count]->ssl, fd);
288
289 n = SSL_accept(this->wsi[this->fds_count]->ssl);
290 if (n != 1) {
291 /*
292 * browsers seem to probe with various
293 * ssl params which fail then retry
294 * and succeed
295 */
296 debug("SSL_accept failed skt %u: %s\n",
297 fd,
298 ERR_error_string(SSL_get_error(
299 this->wsi[this->fds_count]->ssl,
300 n), NULL));
301 SSL_free(
302 this->wsi[this->fds_count]->ssl);
303 free(this->wsi[this->fds_count]);
304 continue;
305 }
306 debug("accepted new SSL conn "
307 "port %u on fd=%d SSL ver %s\n",
308 ntohs(cli_addr.sin_port), fd,
309 SSL_get_version(this->wsi[
310 this->fds_count]->ssl));
311
312 } else
313#endif
314 debug("accepted new conn port %u on fd=%d\n",
315 ntohs(cli_addr.sin_port), fd);
316
317 /* intialize the instance struct */
318
319 this->wsi[this->fds_count]->sock = fd;
320 this->wsi[this->fds_count]->state = WSI_STATE_HTTP;
321 this->wsi[this->fds_count]->name_buffer_pos = 0;
Andy Green4739e5c2011-01-22 12:51:57 +0000322 this->wsi[this->fds_count]->client_mode = 0;
Andy Greene92cd172011-01-19 13:11:55 +0000323
324 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
325 this->wsi[this->fds_count]->
326 utf8_token[n].token = NULL;
327 this->wsi[this->fds_count]->
328 utf8_token[n].token_len = 0;
329 }
330
331 /*
332 * these can only be set once the protocol is known
333 * we set an unestablished connection's protocol pointer
334 * to the start of the supported list, so it can look
335 * for matching ones during the handshake
336 */
337 this->wsi[this->fds_count]->protocol = this->protocols;
338 this->wsi[this->fds_count]->user_space = NULL;
339
340 /*
341 * Default protocol is 76 / 00
342 * After 76, there's a header specified to inform which
343 * draft the client wants, when that's seen we modify
344 * the individual connection's spec revision accordingly
345 */
346 this->wsi[this->fds_count]->ietf_spec_revision = 0;
347
348fill_in_fds:
349
350 /*
351 * make sure NO events are seen yet on this new socket
352 * (otherwise we inherit old fds[client].revents from
353 * previous socket there and die mysteriously! )
354 */
355 this->fds[this->fds_count].revents = 0;
356
357 this->fds[this->fds_count].events = POLLIN;
358 this->fds[this->fds_count++].fd = fd;
359
360 }
361
362 /* service anything incoming on websocket connection */
363
364 libwebsocket_poll_connections(this);
365
366 /* this round is done */
367
368 return 0;
369
370fatal:
371
372 /* close listening skt and per-protocol broadcast sockets */
373 for (client = 0; client < this->fds_count; client++)
374 close(this->fds[0].fd);
375
376#ifdef LWS_OPENSSL_SUPPORT
377 SSL_CTX_free(ssl_ctx);
378#endif
379 kill(0, SIGTERM);
380
381 if (this)
382 free(this);
383
384 this = NULL;
385
386 /* inform caller we are dead */
387
388 return 1;
389}
390
Andy Greenb45993c2010-12-18 15:13:50 +0000391
Andy Greenab990e42010-10-31 12:42:52 +0000392/**
Andy Green4739e5c2011-01-22 12:51:57 +0000393 * libwebsocket_create_context() - Create the websocket handler
394 * @port: Port to listen on... you can use 0 to suppress listening on
395 * any port, that's what you want if you are not running a
396 * websocket server at all but just using it as a client
Andy Green4f3943a2010-11-12 10:44:16 +0000397 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +0000398 * specific callback for each one. The list is ended with an
399 * entry that has a NULL callback pointer.
400 * It's not const because we write the owning_server member
Andy Green3faa9c72010-11-08 17:03:03 +0000401 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +0000402 * to listen using SSL, set to the filepath to fetch the
403 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +0000404 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +0000405 * else ignored
Andy Green3faa9c72010-11-08 17:03:03 +0000406 * @gid: group id to change to after setting listen socket, or -1.
407 * @uid: user id to change to after setting listen socket, or -1.
Andy Green05464c62010-11-12 10:44:18 +0000408 *
Andy Green8f037e42010-12-19 22:13:26 +0000409 * This function creates the listening socket and takes care
410 * of all initialization in one step.
411 *
Andy Greene92cd172011-01-19 13:11:55 +0000412 * After initialization, it returns a struct libwebsocket_context * that
413 * represents this server. After calling, user code needs to take care
414 * of calling libwebsocket_service() with the context pointer to get the
415 * server's sockets serviced. This can be done in the same process context
416 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +0000417 *
Andy Green8f037e42010-12-19 22:13:26 +0000418 * The protocol callback functions are called for a handful of events
419 * including http requests coming in, websocket connections becoming
420 * established, and data arriving; it's also called periodically to allow
421 * async transmission.
422 *
423 * HTTP requests are sent always to the FIRST protocol in @protocol, since
424 * at that time websocket protocol has not been negotiated. Other
425 * protocols after the first one never see any HTTP callack activity.
426 *
427 * The server created is a simple http server by default; part of the
428 * websocket standard is upgrading this http connection to a websocket one.
429 *
430 * This allows the same server to provide files like scripts and favicon /
431 * images or whatever over http and dynamic data over websockets all in
432 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +0000433 */
Andy Green4ea60062010-10-30 12:15:07 +0100434
Andy Greene92cd172011-01-19 13:11:55 +0000435struct libwebsocket_context *
Andy Green4739e5c2011-01-22 12:51:57 +0000436libwebsocket_create_context(int port,
Andy Greenb45993c2010-12-18 15:13:50 +0000437 struct libwebsocket_protocols *protocols,
Andy Green8f037e42010-12-19 22:13:26 +0000438 const char *ssl_cert_filepath,
439 const char *ssl_private_key_filepath,
Andy Greence510c62010-11-11 12:48:13 +0000440 int gid, int uid)
Andy Greenff95d7a2010-10-28 22:36:01 +0100441{
442 int n;
Andy Green4739e5c2011-01-22 12:51:57 +0000443 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +0000444 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +0100445 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +0000446 int opt = 1;
Andy Green8f037e42010-12-19 22:13:26 +0000447 struct libwebsocket_context *this = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000448 unsigned int slen;
Andy Greenff95d7a2010-10-28 22:36:01 +0100449
Andy Green3faa9c72010-11-08 17:03:03 +0000450#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +0000451 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +0000452 char ssl_err_buf[512];
453
454 use_ssl = ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL;
455 if (use_ssl)
456 fprintf(stderr, " Compiled with SSL support, using it\n");
457 else
Andy Green018d8eb2010-11-08 21:04:23 +0000458 fprintf(stderr, " Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +0000459
460#else
461 if (ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL) {
462 fprintf(stderr, " Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +0000463 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000464 }
Andy Green018d8eb2010-11-08 21:04:23 +0000465 fprintf(stderr, " Compiled without SSL support, serving unencrypted\n");
Andy Green3faa9c72010-11-08 17:03:03 +0000466#endif
467
468#ifdef LWS_OPENSSL_SUPPORT
469 if (use_ssl) {
470 SSL_library_init();
471
472 OpenSSL_add_all_algorithms();
473 SSL_load_error_strings();
474
Andy Green0ca6a172010-12-19 20:50:01 +0000475 /*
476 * Firefox insists on SSLv23 not SSLv3
477 * Konq disables SSLv2 by default now, SSLv23 works
478 */
Andy Green3faa9c72010-11-08 17:03:03 +0000479
Andy Greenb45993c2010-12-18 15:13:50 +0000480 method = (SSL_METHOD *)SSLv23_server_method();
Andy Green3faa9c72010-11-08 17:03:03 +0000481 if (!method) {
482 fprintf(stderr, "problem creating ssl method: %s\n",
483 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000484 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000485 }
486 ssl_ctx = SSL_CTX_new(method); /* create context */
487 if (!ssl_ctx) {
488 printf("problem creating ssl context: %s\n",
489 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000490 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000491 }
492 /* set the local certificate from CertFile */
493 n = SSL_CTX_use_certificate_file(ssl_ctx,
494 ssl_cert_filepath, SSL_FILETYPE_PEM);
495 if (n != 1) {
496 fprintf(stderr, "problem getting cert '%s': %s\n",
497 ssl_cert_filepath,
498 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000499 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000500 }
501 /* set the private key from KeyFile */
Andy Green018d8eb2010-11-08 21:04:23 +0000502 if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
503 ssl_private_key_filepath,
Andy Green4739e5c2011-01-22 12:51:57 +0000504 SSL_FILETYPE_PEM) != 1) {
Andy Green018d8eb2010-11-08 21:04:23 +0000505 fprintf(stderr, "ssl problem getting key '%s': %s\n",
506 ssl_private_key_filepath,
507 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +0000508 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000509 }
510 /* verify private key */
511 if (!SSL_CTX_check_private_key(ssl_ctx)) {
Andy Green018d8eb2010-11-08 21:04:23 +0000512 fprintf(stderr, "Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +0000513 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000514 }
515
516 /* SSL is happy and has a cert it's content with */
517 }
518#endif
Andy Greenb45993c2010-12-18 15:13:50 +0000519
Andy Greendf736162011-01-18 15:39:02 +0000520 /* selftest */
521
522 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +0000523 return NULL;
Andy Greendf736162011-01-18 15:39:02 +0000524
525
Andy Green8f037e42010-12-19 22:13:26 +0000526 this = malloc(sizeof(struct libwebsocket_context));
Andy Greenb45993c2010-12-18 15:13:50 +0000527
Andy Greene92cd172011-01-19 13:11:55 +0000528 this->protocols = protocols;
Andy Green4739e5c2011-01-22 12:51:57 +0000529 this->listen_port = port;
Andy Greene92cd172011-01-19 13:11:55 +0000530
Andy Greenb45993c2010-12-18 15:13:50 +0000531 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +0000532
Andy Green4739e5c2011-01-22 12:51:57 +0000533 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +0000534
Andy Green4739e5c2011-01-22 12:51:57 +0000535 sockfd = socket(AF_INET, SOCK_STREAM, 0);
536 if (sockfd < 0) {
537 fprintf(stderr, "ERROR opening socket");
538 return NULL;
539 }
Andy Green775c0dd2010-10-29 14:15:22 +0100540
Andy Green4739e5c2011-01-22 12:51:57 +0000541 /* allow us to restart even if old sockets in TIME_WAIT */
542 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
Andy Greene77ddd82010-11-13 10:03:47 +0000543
Andy Green4739e5c2011-01-22 12:51:57 +0000544 bzero((char *) &serv_addr, sizeof(serv_addr));
545 serv_addr.sin_family = AF_INET;
546 serv_addr.sin_addr.s_addr = INADDR_ANY;
547 serv_addr.sin_port = htons(port);
548
549 n = bind(sockfd, (struct sockaddr *) &serv_addr,
550 sizeof(serv_addr));
551 if (n < 0) {
552 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +0000553 port, n, errno);
Andy Green4739e5c2011-01-22 12:51:57 +0000554 return NULL;
555 }
Andy Green8f037e42010-12-19 22:13:26 +0000556 }
Andy Greenb45993c2010-12-18 15:13:50 +0000557
Andy Greene77ddd82010-11-13 10:03:47 +0000558 /* drop any root privs for this process */
Andy Green3faa9c72010-11-08 17:03:03 +0000559
560 if (gid != -1)
561 if (setgid(gid))
562 fprintf(stderr, "setgid: %s\n", strerror(errno));
563 if (uid != -1)
564 if (setuid(uid))
565 fprintf(stderr, "setuid: %s\n", strerror(errno));
566
Andy Green8f037e42010-12-19 22:13:26 +0000567 /*
Andy Greenb45993c2010-12-18 15:13:50 +0000568 * prepare the poll() fd array... it's like this
569 *
570 * [0] = external listening socket
571 * [1 .. this->count_protocols] = per-protocol broadcast sockets
572 * [this->count_protocols + 1 ... this->fds_count-1] = connection skts
Andy Green4f3943a2010-11-12 10:44:16 +0000573 */
574
Andy Greenb45993c2010-12-18 15:13:50 +0000575 this->fds_count = 1;
576 this->fds[0].fd = sockfd;
577 this->fds[0].events = POLLIN;
578 this->count_protocols = 0;
579#ifdef LWS_OPENSSL_SUPPORT
580 this->use_ssl = use_ssl;
581#endif
582
Andy Green4739e5c2011-01-22 12:51:57 +0000583 if (port) {
584 listen(sockfd, 5);
585 fprintf(stderr, " Listening on port %d\n", port);
586 }
Andy Greenb45993c2010-12-18 15:13:50 +0000587
588 /* set up our internal broadcast trigger sockets per-protocol */
589
590 for (; protocols[this->count_protocols].callback;
591 this->count_protocols++) {
592 protocols[this->count_protocols].owning_server = this;
593 protocols[this->count_protocols].protocol_index =
594 this->count_protocols;
595
596 fd = socket(AF_INET, SOCK_STREAM, 0);
597 if (fd < 0) {
598 fprintf(stderr, "ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +0000599 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000600 }
Andy Green8f037e42010-12-19 22:13:26 +0000601
Andy Greenb45993c2010-12-18 15:13:50 +0000602 /* allow us to restart even if old sockets in TIME_WAIT */
603 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
604
605 bzero((char *) &serv_addr, sizeof(serv_addr));
606 serv_addr.sin_family = AF_INET;
607 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
608 serv_addr.sin_port = 0; /* pick the port for us */
609
610 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
611 if (n < 0) {
Andy Green8f037e42010-12-19 22:13:26 +0000612 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +0000613 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +0000614 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000615 }
616
617 slen = sizeof cli_addr;
618 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
619 if (n < 0) {
620 fprintf(stderr, "getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +0000621 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000622 }
623 protocols[this->count_protocols].broadcast_socket_port =
624 ntohs(cli_addr.sin_port);
625 listen(fd, 5);
626
627 debug(" Protocol %s broadcast socket %d\n",
628 protocols[this->count_protocols].name,
629 ntohs(cli_addr.sin_port));
630
631 this->fds[this->fds_count].fd = fd;
632 this->fds[this->fds_count].events = POLLIN;
633 /* wsi only exists for connections, not broadcast listener */
634 this->wsi[this->fds_count] = NULL;
635 this->fds_count++;
636 }
637
Andy Greene92cd172011-01-19 13:11:55 +0000638 return this;
639}
Andy Greenb45993c2010-12-18 15:13:50 +0000640
Andy Green4739e5c2011-01-22 12:51:57 +0000641
Andy Greened11a022011-01-20 10:23:50 +0000642#ifndef LWS_NO_FORK
643
Andy Greene92cd172011-01-19 13:11:55 +0000644/**
645 * libwebsockets_fork_service_loop() - Optional helper function forks off
646 * a process for the websocket server loop.
647 * You don't have to use this but if not, you
648 * have to make sure you are calling
649 * libwebsocket_service periodically to service
650 * the websocket traffic
651 * @this: server context returned by creation function
652 */
Andy Greenb45993c2010-12-18 15:13:50 +0000653
Andy Greene92cd172011-01-19 13:11:55 +0000654int
655libwebsockets_fork_service_loop(struct libwebsocket_context *this)
656{
657 int client;
658 int fd;
659 struct sockaddr_in cli_addr;
660 int n;
Andy Greenb45993c2010-12-18 15:13:50 +0000661
Andy Greened11a022011-01-20 10:23:50 +0000662 n = fork();
663 if (n < 0)
664 return n;
665
666 if (!n) {
667
668 /* main process context */
669
670 for (client = 1; client < this->count_protocols + 1; client++) {
671 fd = socket(AF_INET, SOCK_STREAM, 0);
672 if (fd < 0) {
673 fprintf(stderr, "Unable to create socket\n");
674 return -1;
675 }
676 cli_addr.sin_family = AF_INET;
677 cli_addr.sin_port = htons(
Andy Green4739e5c2011-01-22 12:51:57 +0000678 this->protocols[client - 1].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +0000679 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
680 n = connect(fd, (struct sockaddr *)&cli_addr,
681 sizeof cli_addr);
682 if (n < 0) {
683 fprintf(stderr, "Unable to connect to "
684 "broadcast socket %d, %s\n",
685 client, strerror(errno));
686 return -1;
687 }
688
Andy Green4739e5c2011-01-22 12:51:57 +0000689 this->protocols[client - 1].broadcast_socket_user_fd =
690 fd;
Andy Greened11a022011-01-20 10:23:50 +0000691 }
692
693
Andy Greene92cd172011-01-19 13:11:55 +0000694 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +0000695 }
696
697 /* we want a SIGHUP when our parent goes down */
698 prctl(PR_SET_PDEATHSIG, SIGHUP);
699
700 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +0000701
Andy Greene92cd172011-01-19 13:11:55 +0000702 while (1)
703 if (libwebsocket_service(this, 1000))
704 return -1;
Andy Green8f037e42010-12-19 22:13:26 +0000705
Andy Green251f6fa2010-11-03 11:13:06 +0000706 return 0;
Andy Greenff95d7a2010-10-28 22:36:01 +0100707}
708
Andy Greened11a022011-01-20 10:23:50 +0000709#endif
710
Andy Greenb45993c2010-12-18 15:13:50 +0000711/**
712 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +0000713 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +0000714 * @wsi: pointer to struct websocket you want to know the protocol of
715 *
Andy Green8f037e42010-12-19 22:13:26 +0000716 *
717 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +0000718 * the callback.
719 */
Andy Greenab990e42010-10-31 12:42:52 +0000720
Andy Greenb45993c2010-12-18 15:13:50 +0000721const struct libwebsocket_protocols *
722libwebsockets_get_protocol(struct libwebsocket *wsi)
723{
724 return wsi->protocol;
725}
726
727/**
Andy Greene92cd172011-01-19 13:11:55 +0000728 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +0000729 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +0000730 * @protocol: pointer to the protocol you will broadcast to all members of
731 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +0000732 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
733 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
734 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +0000735 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +0000736 *
737 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +0000738 * the given protocol. It does not send the data directly; instead it calls
739 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
740 * wants to actually send the data for that connection, the callback itself
741 * should call libwebsocket_write().
742 *
743 * libwebsockets_broadcast() can be called from another fork context without
744 * having to take any care about data visibility between the processes, it'll
745 * "just work".
746 */
747
748
749int
Andy Green8f037e42010-12-19 22:13:26 +0000750libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +0000751 unsigned char *buf, size_t len)
752{
Andy Green8f037e42010-12-19 22:13:26 +0000753 struct libwebsocket_context *this = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +0000754 int n;
755
756 if (!protocol->broadcast_socket_user_fd) {
757 /*
Andy Greene92cd172011-01-19 13:11:55 +0000758 * We are either running unforked / flat, or we are being
759 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +0000760 * eg, from a callback. In that case don't use sockets for
761 * broadcast IPC (since we can't open a socket connection to
762 * a socket listening on our own thread) but directly do the
763 * send action.
764 *
765 * Locking is not needed because we are by definition being
766 * called in the poll thread context and are serialized.
767 */
768
769 for (n = this->count_protocols + 1; n < this->fds_count; n++) {
770
771 if ((unsigned long)this->wsi[n] < LWS_MAX_PROTOCOLS)
772 continue;
773
774 /* never broadcast to non-established connection */
Andy Greenb45993c2010-12-18 15:13:50 +0000775 if (this->wsi[n]->state != WSI_STATE_ESTABLISHED)
776 continue;
777
778 /* only broadcast to guys using requested protocol */
Andy Greenb45993c2010-12-18 15:13:50 +0000779 if (this->wsi[n]->protocol != protocol)
780 continue;
781
Andy Green8f037e42010-12-19 22:13:26 +0000782 this->wsi[n]->protocol->callback(this->wsi[n],
783 LWS_CALLBACK_BROADCAST,
Andy Greenb45993c2010-12-18 15:13:50 +0000784 this->wsi[n]->user_space,
785 buf, len);
786 }
787
788 return 0;
789 }
790
Andy Green0ca6a172010-12-19 20:50:01 +0000791 /*
792 * We're being called from a different process context than the server
793 * loop. Instead of broadcasting directly, we send our
794 * payload on a socket to do the IPC; the server process will serialize
795 * the broadcast action in its main poll() loop.
796 *
797 * There's one broadcast socket listening for each protocol supported
798 * set up when the websocket server initializes
799 */
800
Andy Greenb45993c2010-12-18 15:13:50 +0000801 n = send(protocol->broadcast_socket_user_fd, buf, len, 0);
802
803 return n;
804}