blob: 46aa18290f3f135b5b073faa85bcbb17e7ef3a6a [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));
Joakim Soderbergb82b0dd2013-02-22 09:28:15 +080049 lwsl_err("*** %lu %s\n", err, buf);
Andy Greena1ce6be2013-01-18 11:43:21 +080050 }
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 Greena1ce6be2013-01-18 11:43:21 +0800103 new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
Andy Green224149a2013-02-11 21:43:41 +0800104 new_wsi->hdr_parsing_completed = 0;
Andy Greena1ce6be2013-01-18 11:43:21 +0800105
Andy Green16ab3182013-02-10 18:02:31 +0800106 if (lws_allocate_header_table(new_wsi)) {
107 free(new_wsi);
108 return NULL;
Andy Greena1ce6be2013-01-18 11:43:21 +0800109 }
110
111 /*
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
116 */
117 new_wsi->protocol = context->protocols;
118 new_wsi->user_space = NULL;
Andy Greena1ce6be2013-01-18 11:43:21 +0800119 new_wsi->ietf_spec_revision = 0;
120
121 return new_wsi;
122}
123
124int lws_server_socket_service(struct libwebsocket_context *context,
125 struct libwebsocket *wsi, struct pollfd *pollfd)
126{
Andy Greena1ce6be2013-01-18 11:43:21 +0800127 struct libwebsocket *new_wsi;
128 int accept_fd;
129 unsigned int clilen;
130 struct sockaddr_in cli_addr;
131 int n;
Andy Greena1ce6be2013-01-18 11:43:21 +0800132 ssize_t len;
Edwin van den Oetelaar0794af92013-01-28 21:53:53 +0800133#ifdef LWS_OPENSSL_SUPPORT
134 int m;
Andy Green23c5f2e2013-02-06 15:43:00 +0900135#ifndef USE_CYASSL
Andy Green1167dd42013-01-28 17:45:34 +0800136 BIO *bio;
Edwin van den Oetelaar0794af92013-01-28 21:53:53 +0800137#endif
Andy Green23c5f2e2013-02-06 15:43:00 +0900138#endif
Andy Greena1ce6be2013-01-18 11:43:21 +0800139
140 switch (wsi->mode) {
141
142 case LWS_CONNMODE_HTTP_SERVING:
143
144 /* handle http headers coming in */
145
146 /* any incoming data ready? */
147
148 if (pollfd->revents & POLLIN) {
149
150 #ifdef LWS_OPENSSL_SUPPORT
151 if (wsi->ssl)
Andy Greenb5b23192013-02-11 17:13:32 +0800152 len = SSL_read(wsi->ssl,
153 context->service_buffer,
154 sizeof(context->service_buffer));
Andy Greena1ce6be2013-01-18 11:43:21 +0800155 else
156 #endif
Andy Greenb5b23192013-02-11 17:13:32 +0800157 len = recv(pollfd->fd,
158 context->service_buffer,
159 sizeof(context->service_buffer), 0);
Andy Greena1ce6be2013-01-18 11:43:21 +0800160
161 if (len < 0) {
162 lwsl_debug("Socket read returned %d\n", len);
163 if (errno != EINTR && errno != EAGAIN)
Andy Greenb5b23192013-02-11 17:13:32 +0800164 libwebsocket_close_and_free_session(
165 context, wsi,
166 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800167 return 0;
168 }
169 if (!len) {
Andy Green224149a2013-02-11 21:43:41 +0800170 lwsl_info("lws_server_skt_srv: read 0 len\n");
171 /* lwsl_info(" state=%d\n", wsi->state); */
172 if (!wsi->hdr_parsing_completed)
173 free(wsi->u.hdr.ah);
Andy Greenb5b23192013-02-11 17:13:32 +0800174 libwebsocket_close_and_free_session(
175 context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800176 return 0;
177 }
178
Andy Greenb5b23192013-02-11 17:13:32 +0800179 n = libwebsocket_read(context, wsi,
180 context->service_buffer, len);
Andy Greena1ce6be2013-01-18 11:43:21 +0800181 if (n < 0)
182 /* we closed wsi */
183 return 0;
184 }
185
186 /* this handles POLLOUT for http serving fragments */
187
188 if (!(pollfd->revents & POLLOUT))
189 break;
190
191 /* one shot */
192 pollfd->events &= ~POLLOUT;
Andy Greenb5b23192013-02-11 17:13:32 +0800193
Andy Green54cb3462013-02-14 22:23:54 +0800194 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,
199 wsi->user_space,
200 NULL,
201 0);
202 if (n < 0)
203 libwebsocket_close_and_free_session(
204 context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800205 break;
Andy Green54cb3462013-02-14 22:23:54 +0800206 }
Andy Greena1ce6be2013-01-18 11:43:21 +0800207
Andy Greenb5b23192013-02-11 17:13:32 +0800208 /* nonzero for completion or error */
209 if (libwebsockets_serve_http_file_fragment(context, wsi))
Andy Greena1ce6be2013-01-18 11:43:21 +0800210 libwebsocket_close_and_free_session(context, wsi,
211 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800212 break;
213
214 case LWS_CONNMODE_SERVER_LISTENER:
215
216 /* pollin means a client has connected to us then */
217
218 if (!(pollfd->revents & POLLIN))
219 break;
220
221 /* listen socket got an unencrypted connection... */
222
223 clilen = sizeof(cli_addr);
Andy Greene000a702013-01-29 12:37:35 +0800224 lws_latency_pre(context, wsi);
Andy Greena1ce6be2013-01-18 11:43:21 +0800225 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
226 &clilen);
Andy Greenb5b23192013-02-11 17:13:32 +0800227 lws_latency(context, wsi,
228 "unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
229 accept_fd, accept_fd >= 0);
Andy Greena1ce6be2013-01-18 11:43:21 +0800230 if (accept_fd < 0) {
Andy Greene2160712013-01-28 12:19:10 +0800231 if (errno == EAGAIN || errno == EWOULDBLOCK) {
232 lwsl_debug("accept asks to try again\n");
233 break;
234 }
Andy Greena1ce6be2013-01-18 11:43:21 +0800235 lwsl_warn("ERROR on accept: %s\n", strerror(errno));
236 break;
237 }
238
Andy Greena690cd02013-02-09 12:25:31 +0800239 lws_set_socket_options(context, accept_fd);
Andy Green6f047ee2013-01-28 11:23:52 +0800240
Andy Greena1ce6be2013-01-18 11:43:21 +0800241 /*
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]
245 */
246
247 if ((context->protocols[0].callback)(context, wsi,
248 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Edwin van den Oetelaar8c8a8e12013-02-20 20:56:59 +0800249 NULL, (void *)(long)accept_fd, 0)) {
Andy Greena1ce6be2013-01-18 11:43:21 +0800250 lwsl_debug("Callback denied network connection\n");
251 compatible_close(accept_fd);
252 break;
253 }
254
255 new_wsi = libwebsocket_create_new_server_wsi(context);
256 if (new_wsi == NULL) {
257 compatible_close(accept_fd);
258 break;
259 }
260
261 new_wsi->sock = accept_fd;
262
Andy Greena1ce6be2013-01-18 11:43:21 +0800263#ifdef LWS_OPENSSL_SUPPORT
264 new_wsi->ssl = NULL;
Andy Greene2160712013-01-28 12:19:10 +0800265 if (!context->use_ssl) {
Andy Greena1ce6be2013-01-18 11:43:21 +0800266#endif
Andy Greene2160712013-01-28 12:19:10 +0800267
Andy Greena1ce6be2013-01-18 11:43:21 +0800268 lwsl_debug("accepted new conn port %u on fd=%d\n",
269 ntohs(cli_addr.sin_port), accept_fd);
270
Andy Greene2160712013-01-28 12:19:10 +0800271 insert_wsi_socket_into_fds(context, new_wsi);
272 break;
273#ifdef LWS_OPENSSL_SUPPORT
274 }
275
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();
282 free(new_wsi);
283 compatible_close(accept_fd);
284 break;
285 }
286
287 SSL_set_ex_data(new_wsi->ssl,
288 openssl_websocket_private_data_index, context);
289
290 SSL_set_fd(new_wsi->ssl, accept_fd);
291
Joakim Soderbergb378ce92013-02-06 15:29:18 +0900292 #ifdef USE_CYASSL
293 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
294 #else
Andy Green1167dd42013-01-28 17:45:34 +0800295 bio = SSL_get_rbio(new_wsi->ssl);
296 if (bio)
297 BIO_set_nbio(bio, 1); /* nonblocking */
298 else
299 lwsl_notice("NULL rbio\n");
300 bio = SSL_get_wbio(new_wsi->ssl);
301 if (bio)
302 BIO_set_nbio(bio, 1); /* nonblocking */
303 else
304 lwsl_notice("NULL rbio\n");
Joakim Soderbergb378ce92013-02-06 15:29:18 +0900305 #endif
Andy Green1167dd42013-01-28 17:45:34 +0800306
Andy Greenb5b23192013-02-11 17:13:32 +0800307 /*
Andy Greene2160712013-01-28 12:19:10 +0800308 * 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
311 */
312
313 wsi = new_wsi;
314 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
315 insert_wsi_socket_into_fds(context, wsi);
316
Andy Greenba85a7d2013-01-28 17:20:41 +0800317 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
318 AWAITING_TIMEOUT);
319
Andy Greenb5b23192013-02-11 17:13:32 +0800320 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
Andy Greene2160712013-01-28 12:19:10 +0800321
322 /* fallthru */
323
324 case LWS_CONNMODE_SSL_ACK_PENDING:
325
326 pollfd->events &= ~POLLOUT;
327
328 /* external POLL support via protocol 0 */
329 context->protocols[0].callback(context, wsi,
330 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
Andy Green0c2f4d82013-02-19 19:19:51 +0800331 wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
Andy Greene2160712013-01-28 12:19:10 +0800332
Andy Greene000a702013-01-29 12:37:35 +0800333 lws_latency_pre(context, wsi);
Andy Greene2160712013-01-28 12:19:10 +0800334 n = SSL_accept(wsi->ssl);
Andy Greenb5b23192013-02-11 17:13:32 +0800335 lws_latency(context, wsi,
336 "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
Andy Greene2160712013-01-28 12:19:10 +0800337
338 if (n != 1) {
339 m = SSL_get_error(wsi->ssl, n);
Andy Greenb5b23192013-02-11 17:13:32 +0800340 lwsl_debug("SSL_accept failed %d / %s\n",
341 m, ERR_error_string(m, NULL));
Andy Greene2160712013-01-28 12:19:10 +0800342
343 if (m == SSL_ERROR_WANT_READ) {
Andy Greenb5b23192013-02-11 17:13:32 +0800344 context->fds[
345 wsi->position_in_fds_table].events |= POLLIN;
Andy Greene2160712013-01-28 12:19:10 +0800346
347 /* external POLL support via protocol 0 */
348 context->protocols[0].callback(context, wsi,
349 LWS_CALLBACK_SET_MODE_POLL_FD,
Andy Green0c2f4d82013-02-19 19:19:51 +0800350 wsi->user_space,
351 (void *)(long)wsi->sock, POLLIN);
Andy Greene2160712013-01-28 12:19:10 +0800352 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,
Andy Green0c2f4d82013-02-19 19:19:51 +0800362 wsi->user_space,
363 (void *)(long)wsi->sock, POLLOUT);
Andy Greene2160712013-01-28 12:19:10 +0800364 break;
365 }
366 lwsl_debug("SSL_accept failed skt %u: %s\n",
367 pollfd->fd,
368 ERR_error_string(m, NULL));
Andy Greenb5b23192013-02-11 17:13:32 +0800369 libwebsocket_close_and_free_session(context, wsi,
370 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greene2160712013-01-28 12:19:10 +0800371 break;
372 }
373
374 /* OK, we are accepted */
375
Andy Greenba85a7d2013-01-28 17:20:41 +0800376 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
377
Andy Greene2160712013-01-28 12:19:10 +0800378 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
379
Andy Green35517092013-02-11 20:10:56 +0800380 lwsl_debug("accepted new SSL conn\n");
Andy Greena1ce6be2013-01-18 11:43:21 +0800381 break;
Andy Greene2160712013-01-28 12:19:10 +0800382#endif
383
Andy Greena1ce6be2013-01-18 11:43:21 +0800384 default:
385 break;
386 }
387 return 0;
388}
Joakim Soderberg63ff1202013-02-11 17:52:23 +0100389