2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010 Andy Green <andy@warmcat.com>
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.
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.
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,
22 #include "private-libwebsockets.h"
24 #ifdef LWS_OPENSSL_SUPPORT
30 libwebsocket_close_and_free_session(struct libwebsocket *wsi)
34 if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
39 wsi->state = WSI_STATE_DEAD_SOCKET;
41 if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED)
42 wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED,
43 wsi->user_space, NULL, 0);
45 for (n = 0; n < WSI_TOKEN_COUNT; n++)
46 if (wsi->utf8_token[n].token)
47 free(wsi->utf8_token[n].token);
49 /* fprintf(stderr, "closing fd=%d\n", wsi->sock); */
51 #ifdef LWS_OPENSSL_SUPPORT
53 n = SSL_get_fd(wsi->ssl);
54 SSL_shutdown(wsi->ssl);
59 shutdown(wsi->sock, SHUT_RDWR);
61 #ifdef LWS_OPENSSL_SUPPORT
65 free(wsi->user_space);
71 libwebsocket_poll_connections(struct libwebsocket_context *this)
73 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BROADCAST_PAYLOAD +
74 LWS_SEND_BUFFER_POST_PADDING];
75 int client = this->count_protocols + 1;
76 struct libwebsocket *wsi;
80 /* check for activity on client sockets */
82 for (; client < this->fds_count; client++) {
84 /* handle session socket closed */
86 if (this->fds[client].revents & (POLLERR | POLLHUP)) {
88 debug("Session Socket %d %p (fd=%d) dead\n",
89 client, this->wsi[client], this->fds[client]);
91 libwebsocket_close_and_free_session(this->wsi[client]);
95 /* any incoming data ready? */
97 if (!(this->fds[client].revents & POLLIN))
102 if ((unsigned long)this->wsi[client] < LWS_MAX_PROTOCOLS) {
104 /* get the issued broadcast payload from the socket */
106 len = read(this->fds[client].fd,
107 buf + LWS_SEND_BUFFER_PRE_PADDING,
108 MAX_BROADCAST_PAYLOAD);
112 "Error reading broadcast payload\n");
116 /* broadcast it to all guys with this protocol index */
118 for (n = this->count_protocols + 1;
119 n < this->fds_count; n++) {
123 if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
127 * never broadcast to non-established
131 if (wsi->state != WSI_STATE_ESTABLISHED)
135 * only broadcast to connections using
136 * the requested protocol
139 if (wsi->protocol->protocol_index !=
140 (int)(unsigned long)this->wsi[client])
143 /* broadcast it to this connection */
145 wsi->protocol->callback(wsi,
146 LWS_CALLBACK_BROADCAST,
148 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
154 #ifdef LWS_OPENSSL_SUPPORT
156 n = SSL_read(this->wsi[client]->ssl, buf, sizeof buf);
159 n = recv(this->fds[client].fd, buf, sizeof buf, 0);
162 fprintf(stderr, "Socket read returned %d\n", n);
166 libwebsocket_close_and_free_session(this->wsi[client]);
170 /* service incoming data */
172 if (libwebsocket_read(this->wsi[client], buf, n) >= 0)
176 * it closed and nuked wsi[client], so remove the
177 * socket handle and wsi from our service list
181 debug("nuking wsi %p, fsd_count = %d\n",
182 this->wsi[client], this->fds_count - 1);
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];
197 libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
202 struct sockaddr_in cli_addr;
205 /* stay dead once we are dead */
210 n = poll(this->fds, this->fds_count, timeout_ms);
212 if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
213 fprintf(stderr, "Listen Socket dead\n");
216 if (n == 0) /* poll timeout */
219 /* handle accept on listening socket? */
221 for (client = 0; client < this->count_protocols + 1; client++) {
223 if (!this->fds[client].revents & POLLIN)
226 /* listen socket got an unencrypted connection... */
228 clilen = sizeof(cli_addr);
229 fd = accept(this->fds[client].fd,
230 (struct sockaddr *)&cli_addr, &clilen);
232 fprintf(stderr, "ERROR on accept");
236 if (this->fds_count >= MAX_CLIENTS) {
237 fprintf(stderr, "too busy");
244 * accepting a connection to broadcast socket
245 * set wsi to be protocol index not pointer
248 this->wsi[this->fds_count] =
249 (struct libwebsocket *)(long)(client - 1);
254 /* accepting connection to main listener */
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");
263 #ifdef LWS_OPENSSL_SUPPORT
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),
272 free(this->wsi[this->fds_count]);
276 SSL_set_fd(this->wsi[this->fds_count]->ssl, fd);
278 n = SSL_accept(this->wsi[this->fds_count]->ssl);
281 * browsers seem to probe with various
282 * ssl params which fail then retry
285 debug("SSL_accept failed skt %u: %s\n",
287 ERR_error_string(SSL_get_error(
288 this->wsi[this->fds_count]->ssl,
291 this->wsi[this->fds_count]->ssl);
292 free(this->wsi[this->fds_count]);
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));
303 debug("accepted new conn port %u on fd=%d\n",
304 ntohs(cli_addr.sin_port), fd);
306 /* intialize the instance struct */
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;
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;
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
325 this->wsi[this->fds_count]->protocol = this->protocols;
326 this->wsi[this->fds_count]->user_space = NULL;
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
334 this->wsi[this->fds_count]->ietf_spec_revision = 0;
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! )
343 this->fds[this->fds_count].revents = 0;
345 this->fds[this->fds_count].events = POLLIN;
346 this->fds[this->fds_count++].fd = fd;
350 /* service anything incoming on websocket connection */
352 libwebsocket_poll_connections(this);
354 /* this round is done */
360 /* close listening skt and per-protocol broadcast sockets */
361 for (client = 0; client < this->fds_count; client++)
362 close(this->fds[0].fd);
364 #ifdef LWS_OPENSSL_SUPPORT
365 SSL_CTX_free(ssl_ctx);
374 /* inform caller we are dead */
381 * libwebsocket_create_server() - Create the listening websockets server
382 * @port: Port to listen on
383 * @protocols: Array of structures listing supported protocols and a protocol-
384 * 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
387 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
388 * to listen using SSL, set to the filepath to fetch the
389 * server cert from, otherwise NULL for unencrypted
390 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
392 * @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.
395 * This function creates the listening socket and takes care
396 * of all initialization in one step.
398 * 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,
404 * 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.
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.
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.
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.
421 struct libwebsocket_context *
422 libwebsocket_create_server(int port,
423 struct libwebsocket_protocols *protocols,
424 const char *ssl_cert_filepath,
425 const char *ssl_private_key_filepath,
431 struct sockaddr_in serv_addr, cli_addr;
433 struct libwebsocket_context *this = NULL;
436 #ifdef LWS_OPENSSL_SUPPORT
438 char ssl_err_buf[512];
440 use_ssl = ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL;
442 fprintf(stderr, " Compiled with SSL support, using it\n");
444 fprintf(stderr, " Compiled with SSL support, not using it\n");
447 if (ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL) {
448 fprintf(stderr, " Not compiled for OpenSSl support!\n");
451 fprintf(stderr, " Compiled without SSL support, serving unencrypted\n");
454 #ifdef LWS_OPENSSL_SUPPORT
458 OpenSSL_add_all_algorithms();
459 SSL_load_error_strings();
462 * Firefox insists on SSLv23 not SSLv3
463 * Konq disables SSLv2 by default now, SSLv23 works
466 method = (SSL_METHOD *)SSLv23_server_method();
468 fprintf(stderr, "problem creating ssl method: %s\n",
469 ERR_error_string(ERR_get_error(), ssl_err_buf));
472 ssl_ctx = SSL_CTX_new(method); /* create context */
474 printf("problem creating ssl context: %s\n",
475 ERR_error_string(ERR_get_error(), ssl_err_buf));
478 /* set the local certificate from CertFile */
479 n = SSL_CTX_use_certificate_file(ssl_ctx,
480 ssl_cert_filepath, SSL_FILETYPE_PEM);
482 fprintf(stderr, "problem getting cert '%s': %s\n",
484 ERR_error_string(ERR_get_error(), ssl_err_buf));
487 /* set the private key from KeyFile */
488 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));
496 /* verify private key */
497 if (!SSL_CTX_check_private_key(ssl_ctx)) {
498 fprintf(stderr, "Private SSL key doesn't match cert\n");
502 /* SSL is happy and has a cert it's content with */
508 if (lws_b64_selftest())
512 this = malloc(sizeof(struct libwebsocket_context));
514 this->protocols = protocols;
516 /* set up our external listening socket we serve on */
518 sockfd = socket(AF_INET, SOCK_STREAM, 0);
520 fprintf(stderr, "ERROR opening socket");
524 /* allow us to restart even if old sockets in TIME_WAIT */
525 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
527 bzero((char *) &serv_addr, sizeof(serv_addr));
528 serv_addr.sin_family = AF_INET;
529 serv_addr.sin_addr.s_addr = INADDR_ANY;
530 serv_addr.sin_port = htons(port);
532 n = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
534 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
539 /* drop any root privs for this process */
543 fprintf(stderr, "setgid: %s\n", strerror(errno));
546 fprintf(stderr, "setuid: %s\n", strerror(errno));
549 * prepare the poll() fd array... it's like this
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
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;
565 fprintf(stderr, " Listening on port %d\n", port);
567 /* set up our internal broadcast trigger sockets per-protocol */
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;
575 fd = socket(AF_INET, SOCK_STREAM, 0);
577 fprintf(stderr, "ERROR opening socket");
581 /* allow us to restart even if old sockets in TIME_WAIT */
582 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
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 */
589 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
591 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
596 slen = sizeof cli_addr;
597 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
599 fprintf(stderr, "getsockname failed\n");
602 protocols[this->count_protocols].broadcast_socket_port =
603 ntohs(cli_addr.sin_port);
606 debug(" Protocol %s broadcast socket %d\n",
607 protocols[this->count_protocols].name,
608 ntohs(cli_addr.sin_port));
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;
623 * libwebsockets_fork_service_loop() - Optional helper function forks off
624 * a process for the websocket server loop.
625 * You don't have to use this but if not, you
626 * have to make sure you are calling
627 * libwebsocket_service periodically to service
628 * the websocket traffic
629 * @this: server context returned by creation function
633 libwebsockets_fork_service_loop(struct libwebsocket_context *this)
637 struct sockaddr_in cli_addr;
646 /* main process context */
648 for (client = 1; client < this->count_protocols + 1; client++) {
649 fd = socket(AF_INET, SOCK_STREAM, 0);
651 fprintf(stderr, "Unable to create socket\n");
654 cli_addr.sin_family = AF_INET;
655 cli_addr.sin_port = htons(
656 this->protocols[client - 1].broadcast_socket_port);
657 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
658 n = connect(fd, (struct sockaddr *)&cli_addr,
661 fprintf(stderr, "Unable to connect to "
662 "broadcast socket %d, %s\n",
663 client, strerror(errno));
667 this->protocols[client - 1].broadcast_socket_user_fd = fd;
674 /* we want a SIGHUP when our parent goes down */
675 prctl(PR_SET_PDEATHSIG, SIGHUP);
677 /* in this forked process, sit and service websocket connections */
680 if (libwebsocket_service(this, 1000))
689 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
691 * @wsi: pointer to struct websocket you want to know the protocol of
694 * This is useful to get the protocol to broadcast back to from inside
698 const struct libwebsocket_protocols *
699 libwebsockets_get_protocol(struct libwebsocket *wsi)
701 return wsi->protocol;
705 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
706 * connections of the given protocol.
707 * @protocol: pointer to the protocol you will broadcast to all members of
708 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
709 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
710 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
711 * case you are calling this function from callback context.
712 * @len: length of payload data in buf, starting from buf.
714 * This function allows bulk sending of a packet to every connection using
715 * the given protocol. It does not send the data directly; instead it calls
716 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
717 * wants to actually send the data for that connection, the callback itself
718 * should call libwebsocket_write().
720 * libwebsockets_broadcast() can be called from another fork context without
721 * having to take any care about data visibility between the processes, it'll
727 libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
728 unsigned char *buf, size_t len)
730 struct libwebsocket_context *this = protocol->owning_server;
733 if (!protocol->broadcast_socket_user_fd) {
735 * We are either running unforked / flat, or we are being
736 * called from poll thread context
737 * eg, from a callback. In that case don't use sockets for
738 * broadcast IPC (since we can't open a socket connection to
739 * a socket listening on our own thread) but directly do the
742 * Locking is not needed because we are by definition being
743 * called in the poll thread context and are serialized.
746 for (n = this->count_protocols + 1; n < this->fds_count; n++) {
748 if ((unsigned long)this->wsi[n] < LWS_MAX_PROTOCOLS)
751 /* never broadcast to non-established connection */
753 if (this->wsi[n]->state != WSI_STATE_ESTABLISHED)
756 /* only broadcast to guys using requested protocol */
758 if (this->wsi[n]->protocol != protocol)
761 this->wsi[n]->protocol->callback(this->wsi[n],
762 LWS_CALLBACK_BROADCAST,
763 this->wsi[n]->user_space,
771 * We're being called from a different process context than the server
772 * loop. Instead of broadcasting directly, we send our
773 * payload on a socket to do the IPC; the server process will serialize
774 * the broadcast action in its main poll() loop.
776 * There's one broadcast socket listening for each protocol supported
777 * set up when the websocket server initializes
780 n = send(protocol->broadcast_socket_user_fd, buf, len, 0);