2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2013 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,
23 #include "private-libwebsockets.h"
29 #ifdef LWS_BUILTIN_GETIFADDRS
30 #include <getifaddrs.h>
35 #include <sys/socket.h>
39 #ifdef LWS_OPENSSL_SUPPORT
42 libwebsockets_decode_ssl_error(void)
47 while ((err = ERR_get_error()) != 0) {
48 ERR_error_string_n(err, buf, sizeof(buf));
49 lwsl_err("*** %lu %s\n", err, buf);
55 interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
63 struct sockaddr_in *sin;
66 for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
67 if (strcmp(ifc->ifa_name, ifname))
69 if (ifc->ifa_addr == NULL)
71 sin = (struct sockaddr_in *)ifc->ifa_addr;
72 if (sin->sin_family != AF_INET)
74 memcpy(addr, sin, addrlen);
84 libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
86 struct libwebsocket *new_wsi;
88 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
89 if (new_wsi == NULL) {
90 lwsl_err("Out of memory for new connection\n");
94 memset(new_wsi, 0, sizeof(struct libwebsocket));
95 #ifndef LWS_NO_EXTENSIONS
96 new_wsi->count_active_extensions = 0;
98 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
100 /* intialize the instance struct */
102 new_wsi->state = WSI_STATE_HTTP;
103 new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
104 new_wsi->hdr_parsing_completed = 0;
106 if (lws_allocate_header_table(new_wsi)) {
112 * these can only be set once the protocol is known
113 * we set an unestablished connection's protocol pointer
114 * to the start of the supported list, so it can look
115 * for matching ones during the handshake
117 new_wsi->protocol = context->protocols;
118 new_wsi->user_space = NULL;
119 new_wsi->ietf_spec_revision = 0;
124 int lws_server_socket_service(struct libwebsocket_context *context,
125 struct libwebsocket *wsi, struct pollfd *pollfd)
127 struct libwebsocket *new_wsi;
130 struct sockaddr_in cli_addr;
133 #ifdef LWS_OPENSSL_SUPPORT
142 case LWS_CONNMODE_HTTP_SERVING:
144 /* handle http headers coming in */
146 /* any incoming data ready? */
148 if (pollfd->revents & POLLIN) {
150 #ifdef LWS_OPENSSL_SUPPORT
152 len = SSL_read(wsi->ssl,
153 context->service_buffer,
154 sizeof(context->service_buffer));
157 len = recv(pollfd->fd,
158 context->service_buffer,
159 sizeof(context->service_buffer), 0);
162 lwsl_debug("Socket read returned %d\n", len);
163 if (errno != EINTR && errno != EAGAIN)
164 libwebsocket_close_and_free_session(
166 LWS_CLOSE_STATUS_NOSTATUS);
170 lwsl_info("lws_server_skt_srv: read 0 len\n");
171 /* lwsl_info(" state=%d\n", wsi->state); */
172 if (!wsi->hdr_parsing_completed)
174 libwebsocket_close_and_free_session(
175 context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
179 n = libwebsocket_read(context, wsi,
180 context->service_buffer, len);
186 /* this handles POLLOUT for http serving fragments */
188 if (!(pollfd->revents & POLLOUT))
192 pollfd->events &= ~POLLOUT;
194 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
195 n = user_callback_handle_rxflow(
196 wsi->protocol->callback,
197 wsi->protocol->owning_server,
198 wsi, LWS_CALLBACK_HTTP_WRITEABLE,
203 libwebsocket_close_and_free_session(
204 context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
208 /* nonzero for completion or error */
209 if (libwebsockets_serve_http_file_fragment(context, wsi))
210 libwebsocket_close_and_free_session(context, wsi,
211 LWS_CLOSE_STATUS_NOSTATUS);
214 case LWS_CONNMODE_SERVER_LISTENER:
216 /* pollin means a client has connected to us then */
218 if (!(pollfd->revents & POLLIN))
221 /* listen socket got an unencrypted connection... */
223 clilen = sizeof(cli_addr);
224 lws_latency_pre(context, wsi);
225 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
227 lws_latency(context, wsi,
228 "unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
229 accept_fd, accept_fd >= 0);
231 if (errno == EAGAIN || errno == EWOULDBLOCK) {
232 lwsl_debug("accept asks to try again\n");
235 lwsl_warn("ERROR on accept: %s\n", strerror(errno));
239 lws_set_socket_options(context, accept_fd);
242 * look at who we connected to and give user code a chance
243 * to reject based on client IP. There's no protocol selected
244 * yet so we issue this to protocols[0]
247 if ((context->protocols[0].callback)(context, wsi,
248 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
249 NULL, (void *)(long)accept_fd, 0)) {
250 lwsl_debug("Callback denied network connection\n");
251 compatible_close(accept_fd);
255 new_wsi = libwebsocket_create_new_server_wsi(context);
256 if (new_wsi == NULL) {
257 compatible_close(accept_fd);
261 new_wsi->sock = accept_fd;
263 #ifdef LWS_OPENSSL_SUPPORT
265 if (!context->use_ssl) {
268 lwsl_debug("accepted new conn port %u on fd=%d\n",
269 ntohs(cli_addr.sin_port), accept_fd);
271 insert_wsi_socket_into_fds(context, new_wsi);
273 #ifdef LWS_OPENSSL_SUPPORT
276 new_wsi->ssl = SSL_new(context->ssl_ctx);
277 if (new_wsi->ssl == NULL) {
278 lwsl_err("SSL_new failed: %s\n",
279 ERR_error_string(SSL_get_error(
280 new_wsi->ssl, 0), NULL));
281 libwebsockets_decode_ssl_error();
283 compatible_close(accept_fd);
287 SSL_set_ex_data(new_wsi->ssl,
288 openssl_websocket_private_data_index, context);
290 SSL_set_fd(new_wsi->ssl, accept_fd);
293 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
295 bio = SSL_get_rbio(new_wsi->ssl);
297 BIO_set_nbio(bio, 1); /* nonblocking */
299 lwsl_notice("NULL rbio\n");
300 bio = SSL_get_wbio(new_wsi->ssl);
302 BIO_set_nbio(bio, 1); /* nonblocking */
304 lwsl_notice("NULL rbio\n");
308 * we are not accepted yet, but we need to enter ourselves
309 * as a live connection. That way we can retry when more
310 * pieces come if we're not sorted yet
314 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
315 insert_wsi_socket_into_fds(context, wsi);
317 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
320 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
324 case LWS_CONNMODE_SSL_ACK_PENDING:
326 pollfd->events &= ~POLLOUT;
328 /* external POLL support via protocol 0 */
329 context->protocols[0].callback(context, wsi,
330 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
331 wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
333 lws_latency_pre(context, wsi);
334 n = SSL_accept(wsi->ssl);
335 lws_latency(context, wsi,
336 "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
339 m = SSL_get_error(wsi->ssl, n);
340 lwsl_debug("SSL_accept failed %d / %s\n",
341 m, ERR_error_string(m, NULL));
343 if (m == SSL_ERROR_WANT_READ) {
345 wsi->position_in_fds_table].events |= POLLIN;
347 /* external POLL support via protocol 0 */
348 context->protocols[0].callback(context, wsi,
349 LWS_CALLBACK_SET_MODE_POLL_FD,
351 (void *)(long)wsi->sock, POLLIN);
352 lwsl_info("SSL_ERROR_WANT_READ\n");
355 if (m == SSL_ERROR_WANT_WRITE) {
357 wsi->position_in_fds_table].events |= POLLOUT;
359 /* external POLL support via protocol 0 */
360 context->protocols[0].callback(context, wsi,
361 LWS_CALLBACK_SET_MODE_POLL_FD,
363 (void *)(long)wsi->sock, POLLOUT);
366 lwsl_debug("SSL_accept failed skt %u: %s\n",
368 ERR_error_string(m, NULL));
369 libwebsocket_close_and_free_session(context, wsi,
370 LWS_CLOSE_STATUS_NOSTATUS);
374 /* OK, we are accepted */
376 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
378 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
380 lwsl_debug("accepted new SSL conn\n");