blob: 72d9e08474fcb0cd3f9da0a08753761311bf9cd3 [file] [log] [blame]
Andy Greena1ce6be2013-01-18 11:43:21 +08001/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010-2013 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
23#include "private-libwebsockets.h"
24
25#ifdef WIN32
26#include <tchar.h>
27#include <io.h>
28#else
29#ifdef LWS_BUILTIN_GETIFADDRS
30#include <getifaddrs.h>
31#else
32#include <ifaddrs.h>
33#endif
34#include <sys/un.h>
35#include <sys/socket.h>
36#include <netdb.h>
37#endif
38
39#ifdef LWS_OPENSSL_SUPPORT
Andy Greena1ce6be2013-01-18 11:43:21 +080040
41static void
42libwebsockets_decode_ssl_error(void)
43{
44 char buf[256];
45 u_long err;
46
47 while ((err = ERR_get_error()) != 0) {
48 ERR_error_string_n(err, buf, sizeof(buf));
49 lwsl_err("*** %s\n", buf);
50 }
51}
52#endif
53
54int
55interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
56{
57 int rc = -1;
58#ifdef WIN32
59 /* TODO */
60#else
61 struct ifaddrs *ifr;
62 struct ifaddrs *ifc;
63 struct sockaddr_in *sin;
64
65 getifaddrs(&ifr);
66 for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
67 if (strcmp(ifc->ifa_name, ifname))
68 continue;
69 if (ifc->ifa_addr == NULL)
70 continue;
71 sin = (struct sockaddr_in *)ifc->ifa_addr;
72 if (sin->sin_family != AF_INET)
73 continue;
74 memcpy(addr, sin, addrlen);
75 rc = 0;
76 }
77
78 freeifaddrs(ifr);
79#endif
80 return rc;
81}
82
83struct libwebsocket *
84libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
85{
86 struct libwebsocket *new_wsi;
Andy Greena1ce6be2013-01-18 11:43:21 +080087
88 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
89 if (new_wsi == NULL) {
90 lwsl_err("Out of memory for new connection\n");
91 return NULL;
92 }
93
94 memset(new_wsi, 0, sizeof(struct libwebsocket));
Andy Green3182ece2013-01-20 17:08:31 +080095#ifndef LWS_NO_EXTENSIONS
Andy Greena1ce6be2013-01-18 11:43:21 +080096 new_wsi->count_active_extensions = 0;
Andy Green3182ece2013-01-20 17:08:31 +080097#endif
Andy Greena1ce6be2013-01-18 11:43:21 +080098 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
99
100 /* intialize the instance struct */
101
102 new_wsi->state = WSI_STATE_HTTP;
Andy Green623a98d2013-01-21 11:04:23 +0800103 new_wsi->u.hdr.name_buffer_pos = 0;
Andy Greena1ce6be2013-01-18 11:43:21 +0800104 new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
Andy Green224149a2013-02-11 21:43:41 +0800105 new_wsi->hdr_parsing_completed = 0;
Andy Greena1ce6be2013-01-18 11:43:21 +0800106
Andy Green16ab3182013-02-10 18:02:31 +0800107 if (lws_allocate_header_table(new_wsi)) {
108 free(new_wsi);
109 return NULL;
Andy Greena1ce6be2013-01-18 11:43:21 +0800110 }
111
112 /*
113 * these can only be set once the protocol is known
114 * we set an unestablished connection's protocol pointer
115 * to the start of the supported list, so it can look
116 * for matching ones during the handshake
117 */
118 new_wsi->protocol = context->protocols;
119 new_wsi->user_space = NULL;
Andy Greena1ce6be2013-01-18 11:43:21 +0800120 new_wsi->ietf_spec_revision = 0;
121
122 return new_wsi;
123}
124
125int lws_server_socket_service(struct libwebsocket_context *context,
126 struct libwebsocket *wsi, struct pollfd *pollfd)
127{
Andy Greena1ce6be2013-01-18 11:43:21 +0800128 struct libwebsocket *new_wsi;
129 int accept_fd;
130 unsigned int clilen;
131 struct sockaddr_in cli_addr;
132 int n;
Andy Greena1ce6be2013-01-18 11:43:21 +0800133 ssize_t len;
Edwin van den Oetelaar0794af92013-01-28 21:53:53 +0800134#ifdef LWS_OPENSSL_SUPPORT
135 int m;
Andy Green23c5f2e2013-02-06 15:43:00 +0900136#ifndef USE_CYASSL
Andy Green1167dd42013-01-28 17:45:34 +0800137 BIO *bio;
Edwin van den Oetelaar0794af92013-01-28 21:53:53 +0800138#endif
Andy Green23c5f2e2013-02-06 15:43:00 +0900139#endif
Andy Greena1ce6be2013-01-18 11:43:21 +0800140
141 switch (wsi->mode) {
142
143 case LWS_CONNMODE_HTTP_SERVING:
144
145 /* handle http headers coming in */
146
147 /* any incoming data ready? */
148
149 if (pollfd->revents & POLLIN) {
150
151 #ifdef LWS_OPENSSL_SUPPORT
152 if (wsi->ssl)
Andy Greenb5b23192013-02-11 17:13:32 +0800153 len = SSL_read(wsi->ssl,
154 context->service_buffer,
155 sizeof(context->service_buffer));
Andy Greena1ce6be2013-01-18 11:43:21 +0800156 else
157 #endif
Andy Greenb5b23192013-02-11 17:13:32 +0800158 len = recv(pollfd->fd,
159 context->service_buffer,
160 sizeof(context->service_buffer), 0);
Andy Greena1ce6be2013-01-18 11:43:21 +0800161
162 if (len < 0) {
163 lwsl_debug("Socket read returned %d\n", len);
164 if (errno != EINTR && errno != EAGAIN)
Andy Greenb5b23192013-02-11 17:13:32 +0800165 libwebsocket_close_and_free_session(
166 context, wsi,
167 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800168 return 0;
169 }
170 if (!len) {
Andy Green224149a2013-02-11 21:43:41 +0800171 lwsl_info("lws_server_skt_srv: read 0 len\n");
172 /* lwsl_info(" state=%d\n", wsi->state); */
173 if (!wsi->hdr_parsing_completed)
174 free(wsi->u.hdr.ah);
Andy Greenb5b23192013-02-11 17:13:32 +0800175 libwebsocket_close_and_free_session(
176 context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800177 return 0;
178 }
179
Andy Greenb5b23192013-02-11 17:13:32 +0800180 n = libwebsocket_read(context, wsi,
181 context->service_buffer, len);
Andy Greena1ce6be2013-01-18 11:43:21 +0800182 if (n < 0)
183 /* we closed wsi */
184 return 0;
185 }
186
187 /* this handles POLLOUT for http serving fragments */
188
189 if (!(pollfd->revents & POLLOUT))
190 break;
191
192 /* one shot */
193 pollfd->events &= ~POLLOUT;
Andy Greenb5b23192013-02-11 17:13:32 +0800194
Andy Green54cb3462013-02-14 22:23:54 +0800195 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
196 n = user_callback_handle_rxflow(
197 wsi->protocol->callback,
198 wsi->protocol->owning_server,
199 wsi, LWS_CALLBACK_HTTP_WRITEABLE,
200 wsi->user_space,
201 NULL,
202 0);
203 if (n < 0)
204 libwebsocket_close_and_free_session(
205 context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800206 break;
Andy Green54cb3462013-02-14 22:23:54 +0800207 }
Andy Greena1ce6be2013-01-18 11:43:21 +0800208
Andy Greenb5b23192013-02-11 17:13:32 +0800209 /* nonzero for completion or error */
210 if (libwebsockets_serve_http_file_fragment(context, wsi))
Andy Greena1ce6be2013-01-18 11:43:21 +0800211 libwebsocket_close_and_free_session(context, wsi,
212 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800213 break;
214
215 case LWS_CONNMODE_SERVER_LISTENER:
216
217 /* pollin means a client has connected to us then */
218
219 if (!(pollfd->revents & POLLIN))
220 break;
221
222 /* listen socket got an unencrypted connection... */
223
224 clilen = sizeof(cli_addr);
Andy Greene000a702013-01-29 12:37:35 +0800225 lws_latency_pre(context, wsi);
Andy Greena1ce6be2013-01-18 11:43:21 +0800226 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
227 &clilen);
Andy Greenb5b23192013-02-11 17:13:32 +0800228 lws_latency(context, wsi,
229 "unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
230 accept_fd, accept_fd >= 0);
Andy Greena1ce6be2013-01-18 11:43:21 +0800231 if (accept_fd < 0) {
Andy Greene2160712013-01-28 12:19:10 +0800232 if (errno == EAGAIN || errno == EWOULDBLOCK) {
233 lwsl_debug("accept asks to try again\n");
234 break;
235 }
Andy Greena1ce6be2013-01-18 11:43:21 +0800236 lwsl_warn("ERROR on accept: %s\n", strerror(errno));
237 break;
238 }
239
Andy Greena690cd02013-02-09 12:25:31 +0800240 lws_set_socket_options(context, accept_fd);
Andy Green6f047ee2013-01-28 11:23:52 +0800241
Andy Greena1ce6be2013-01-18 11:43:21 +0800242 /*
243 * look at who we connected to and give user code a chance
244 * to reject based on client IP. There's no protocol selected
245 * yet so we issue this to protocols[0]
246 */
247
248 if ((context->protocols[0].callback)(context, wsi,
249 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
250 (void *)(long)accept_fd, NULL, 0)) {
251 lwsl_debug("Callback denied network connection\n");
252 compatible_close(accept_fd);
253 break;
254 }
255
256 new_wsi = libwebsocket_create_new_server_wsi(context);
257 if (new_wsi == NULL) {
258 compatible_close(accept_fd);
259 break;
260 }
261
262 new_wsi->sock = accept_fd;
263
Andy Greena1ce6be2013-01-18 11:43:21 +0800264#ifdef LWS_OPENSSL_SUPPORT
265 new_wsi->ssl = NULL;
Andy Greene2160712013-01-28 12:19:10 +0800266 if (!context->use_ssl) {
Andy Greena1ce6be2013-01-18 11:43:21 +0800267#endif
Andy Greene2160712013-01-28 12:19:10 +0800268
Andy Greena1ce6be2013-01-18 11:43:21 +0800269 lwsl_debug("accepted new conn port %u on fd=%d\n",
270 ntohs(cli_addr.sin_port), accept_fd);
271
Andy Greene2160712013-01-28 12:19:10 +0800272 insert_wsi_socket_into_fds(context, new_wsi);
273 break;
274#ifdef LWS_OPENSSL_SUPPORT
275 }
276
277 new_wsi->ssl = SSL_new(context->ssl_ctx);
278 if (new_wsi->ssl == NULL) {
279 lwsl_err("SSL_new failed: %s\n",
280 ERR_error_string(SSL_get_error(
281 new_wsi->ssl, 0), NULL));
282 libwebsockets_decode_ssl_error();
283 free(new_wsi);
284 compatible_close(accept_fd);
285 break;
286 }
287
288 SSL_set_ex_data(new_wsi->ssl,
289 openssl_websocket_private_data_index, context);
290
291 SSL_set_fd(new_wsi->ssl, accept_fd);
292
Joakim Soderbergb378ce92013-02-06 15:29:18 +0900293 #ifdef USE_CYASSL
294 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
295 #else
Andy Green1167dd42013-01-28 17:45:34 +0800296 bio = SSL_get_rbio(new_wsi->ssl);
297 if (bio)
298 BIO_set_nbio(bio, 1); /* nonblocking */
299 else
300 lwsl_notice("NULL rbio\n");
301 bio = SSL_get_wbio(new_wsi->ssl);
302 if (bio)
303 BIO_set_nbio(bio, 1); /* nonblocking */
304 else
305 lwsl_notice("NULL rbio\n");
Joakim Soderbergb378ce92013-02-06 15:29:18 +0900306 #endif
Andy Green1167dd42013-01-28 17:45:34 +0800307
Andy Greenb5b23192013-02-11 17:13:32 +0800308 /*
Andy Greene2160712013-01-28 12:19:10 +0800309 * we are not accepted yet, but we need to enter ourselves
310 * as a live connection. That way we can retry when more
311 * pieces come if we're not sorted yet
312 */
313
314 wsi = new_wsi;
315 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
316 insert_wsi_socket_into_fds(context, wsi);
317
Andy Greenba85a7d2013-01-28 17:20:41 +0800318 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
319 AWAITING_TIMEOUT);
320
Andy Greenb5b23192013-02-11 17:13:32 +0800321 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
Andy Greene2160712013-01-28 12:19:10 +0800322
323 /* fallthru */
324
325 case LWS_CONNMODE_SSL_ACK_PENDING:
326
327 pollfd->events &= ~POLLOUT;
328
329 /* external POLL support via protocol 0 */
330 context->protocols[0].callback(context, wsi,
331 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
332 (void *)(long)wsi->sock, NULL, POLLOUT);
333
Andy Greene000a702013-01-29 12:37:35 +0800334 lws_latency_pre(context, wsi);
Andy Greene2160712013-01-28 12:19:10 +0800335 n = SSL_accept(wsi->ssl);
Andy Greenb5b23192013-02-11 17:13:32 +0800336 lws_latency(context, wsi,
337 "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
Andy Greene2160712013-01-28 12:19:10 +0800338
339 if (n != 1) {
340 m = SSL_get_error(wsi->ssl, n);
Andy Greenb5b23192013-02-11 17:13:32 +0800341 lwsl_debug("SSL_accept failed %d / %s\n",
342 m, ERR_error_string(m, NULL));
Andy Greene2160712013-01-28 12:19:10 +0800343
344 if (m == SSL_ERROR_WANT_READ) {
Andy Greenb5b23192013-02-11 17:13:32 +0800345 context->fds[
346 wsi->position_in_fds_table].events |= POLLIN;
Andy Greene2160712013-01-28 12:19:10 +0800347
348 /* external POLL support via protocol 0 */
349 context->protocols[0].callback(context, wsi,
350 LWS_CALLBACK_SET_MODE_POLL_FD,
351 (void *)(long)wsi->sock, NULL, POLLIN);
352 lwsl_info("SSL_ERROR_WANT_READ\n");
353 break;
354 }
355 if (m == SSL_ERROR_WANT_WRITE) {
Andy Greenb5b23192013-02-11 17:13:32 +0800356 context->fds[
357 wsi->position_in_fds_table].events |= POLLOUT;
Andy Greene2160712013-01-28 12:19:10 +0800358
359 /* external POLL support via protocol 0 */
360 context->protocols[0].callback(context, wsi,
361 LWS_CALLBACK_SET_MODE_POLL_FD,
362 (void *)(long)wsi->sock, NULL, POLLOUT);
363 break;
364 }
365 lwsl_debug("SSL_accept failed skt %u: %s\n",
366 pollfd->fd,
367 ERR_error_string(m, NULL));
Andy Greenb5b23192013-02-11 17:13:32 +0800368 libwebsocket_close_and_free_session(context, wsi,
369 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greene2160712013-01-28 12:19:10 +0800370 break;
371 }
372
373 /* OK, we are accepted */
374
Andy Greenba85a7d2013-01-28 17:20:41 +0800375 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
376
Andy Greene2160712013-01-28 12:19:10 +0800377 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
378
Andy Green35517092013-02-11 20:10:56 +0800379 lwsl_debug("accepted new SSL conn\n");
Andy Greena1ce6be2013-01-18 11:43:21 +0800380 break;
Andy Greene2160712013-01-28 12:19:10 +0800381#endif
382
Andy Greena1ce6be2013-01-18 11:43:21 +0800383 default:
384 break;
385 }
386 return 0;
387}
Joakim Soderberg63ff1202013-02-11 17:52:23 +0100388