blob: 4d036a96d2da64f9d72141f7533a07cdc52bab97 [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
Andy Greene38031a2014-04-03 08:24:29 +080025int lws_context_init_server(struct lws_context_creation_info *info,
26 struct libwebsocket_context *context)
27{
28 int n;
29 int sockfd;
30 struct sockaddr_in sin;
31 socklen_t len = sizeof(sin);
32 int opt = 1;
33 struct libwebsocket *wsi;
34#ifdef LWS_USE_IPV6
35 struct sockaddr_in6 serv_addr6;
36#endif
37 struct sockaddr_in serv_addr4;
38 struct sockaddr *v;
39
40 /* set up our external listening socket we serve on */
41
42 if (info->port == CONTEXT_PORT_NO_LISTEN)
43 return 0;
44
45#ifdef LWS_USE_IPV6
46 if (LWS_IPV6_ENABLED(context))
47 sockfd = socket(AF_INET6, SOCK_STREAM, 0);
48 else
49#endif
50 sockfd = socket(AF_INET, SOCK_STREAM, 0);
51
52 if (sockfd < 0) {
53 lwsl_err("ERROR opening socket\n");
54 return 1;
55 }
56
57 /*
58 * allow us to restart even if old sockets in TIME_WAIT
59 */
60 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
61 (const void *)&opt, sizeof(opt));
62
63 lws_plat_set_socket_options(context, sockfd);
64
65#ifdef LWS_USE_IPV6
66 if (LWS_IPV6_ENABLED(context)) {
67 v = (struct sockaddr *)&serv_addr6;
68 n = sizeof(struct sockaddr_in6);
69 bzero((char *) &serv_addr6, sizeof(serv_addr6));
70 serv_addr6.sin6_addr = in6addr_any;
71 serv_addr6.sin6_family = AF_INET6;
72 serv_addr6.sin6_port = htons(info->port);
73 } else
74#endif
75 {
76 v = (struct sockaddr *)&serv_addr4;
77 n = sizeof(serv_addr4);
78 bzero((char *) &serv_addr4, sizeof(serv_addr4));
79 serv_addr4.sin_addr.s_addr = INADDR_ANY;
80 serv_addr4.sin_family = AF_INET;
Andy Greene38031a2014-04-03 08:24:29 +080081
82 if (info->iface) {
83 if (interface_to_sa(context, info->iface,
84 (struct sockaddr_in *)v, n) < 0) {
85 lwsl_err("Unable to find interface %s\n",
86 info->iface);
87 compatible_close(sockfd);
88 return 1;
89 }
90 }
vpeter47cc7ae42014-04-27 12:32:15 +020091
92 serv_addr4.sin_port = htons(info->port);
Andy Greene38031a2014-04-03 08:24:29 +080093 } /* ipv4 */
94
95 n = bind(sockfd, v, n);
96 if (n < 0) {
97 lwsl_err("ERROR on binding to port %d (%d %d)\n",
98 info->port, n, LWS_ERRNO);
99 compatible_close(sockfd);
100 return 1;
101 }
102
103 if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
104 lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
105 else
106 info->port = ntohs(sin.sin_port);
107
108 context->listen_port = info->port;
109
110 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
111 if (wsi == NULL) {
112 lwsl_err("Out of mem\n");
113 compatible_close(sockfd);
114 return 1;
115 }
116 memset(wsi, 0, sizeof(struct libwebsocket));
117 wsi->sock = sockfd;
118 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
119
120 insert_wsi_socket_into_fds(context, wsi);
121
122 context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
123 context->listen_service_count = 0;
124 context->listen_service_fd = sockfd;
125
126 listen(sockfd, LWS_SOMAXCONN);
127 lwsl_notice(" Listening on port %d\n", info->port);
128
129 return 0;
130}
131
Andy Greend99476b2014-04-03 08:40:05 +0800132int
133_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
134{
135 struct libwebsocket_context *context = wsi->protocol->owning_server;
136
137 /* there is no pending change */
Andy Green024eb6c2014-10-08 12:00:53 +0800138 if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
Andy Greend99476b2014-04-03 08:40:05 +0800139 return 0;
140
141 /* stuff is still buffered, not ready to really accept new input */
Andy Green024eb6c2014-10-08 12:00:53 +0800142 if (wsi->rxflow_buffer) {
Andy Greend99476b2014-04-03 08:40:05 +0800143 /* get ourselves called back to deal with stashed buffer */
144 libwebsocket_callback_on_writable(context, wsi);
145 return 0;
146 }
147
148 /* pending is cleared, we can change rxflow state */
149
Andy Green024eb6c2014-10-08 12:00:53 +0800150 wsi->rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;
Andy Greend99476b2014-04-03 08:40:05 +0800151
152 lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
Andy Green024eb6c2014-10-08 12:00:53 +0800153 wsi->rxflow_change_to & LWS_RXFLOW_ALLOW);
Andy Greend99476b2014-04-03 08:40:05 +0800154
155 /* adjust the pollfd for this wsi */
156
Andy Green024eb6c2014-10-08 12:00:53 +0800157 if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) {
Andy Greena717df22014-04-11 13:14:37 +0800158 if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
159 lwsl_info("%s: fail\n", __func__);
Andy Greend99476b2014-04-03 08:40:05 +0800160 return -1;
Andy Greena717df22014-04-11 13:14:37 +0800161 }
Andy Greend99476b2014-04-03 08:40:05 +0800162 } else
163 if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
164 return -1;
165
Andy Greenf004ec52014-04-12 11:47:25 +0800166 return 0;
Andy Greend99476b2014-04-03 08:40:05 +0800167}
168
Andy Green024eb6c2014-10-08 12:00:53 +0800169int lws_http_action(struct libwebsocket_context *context,
170 struct libwebsocket *wsi)
171{
172 char *uri_ptr = NULL;
173 int uri_len = 0;
174 enum http_version request_version;
175 enum http_connection_type connection_type;
176 int http_version_len;
177 char content_length_str[32];
178 char http_version_str[10];
179 char http_conn_str[20];
180 int n;
181
182 /* it's not websocket.... shall we accept it as http? */
183
184 if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
185 !lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) &&
186 !lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
187 lwsl_warn("Missing URI in HTTP request\n");
188 goto bail_nuke_ah;
189 }
190
191 if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
192 lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
193 lwsl_warn("GET and POST methods?\n");
194 goto bail_nuke_ah;
195 }
196
197 if (libwebsocket_ensure_user_space(wsi))
198 goto bail_nuke_ah;
199
200 if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
201 uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
202 uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
203 lwsl_info("HTTP GET request for '%s'\n",
204 lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
205 }
206 if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
207 lwsl_info("HTTP POST request for '%s'\n",
208 lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI));
209 uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI);
210 uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
211 }
212 if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
213 lwsl_info("HTTP OPTIONS request for '%s'\n",
214 lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI));
215 uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI);
216 uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI);
217 }
218
219 /* HTTP header had a content length? */
220
221 wsi->u.http.content_length = 0;
222 if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
223 wsi->u.http.content_length = 100 * 1024 * 1024;
224
225 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
226 lws_hdr_copy(wsi, content_length_str,
227 sizeof(content_length_str) - 1,
228 WSI_TOKEN_HTTP_CONTENT_LENGTH);
229 wsi->u.http.content_length = atoi(content_length_str);
230 }
231
232 /* http_version? Default to 1.0, override with token: */
233 request_version = HTTP_VERSION_1_0;
234
235 /* Works for single digit HTTP versions. : */
236 http_version_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP);
237 if (http_version_len > 7) {
238 lws_hdr_copy(wsi, http_version_str,
239 sizeof(http_version_str) - 1, WSI_TOKEN_HTTP);
240 if (http_version_str[5] == '1' && http_version_str[7] == '1')
241 request_version = HTTP_VERSION_1_1;
242 }
243 wsi->u.http.request_version = request_version;
244
245 /* HTTP/1.1 defaults to "keep-alive", 1.0 to "close" */
246 if (request_version == HTTP_VERSION_1_1)
247 connection_type = HTTP_CONNECTION_KEEP_ALIVE;
248 else
249 connection_type = HTTP_CONNECTION_CLOSE;
250
251 /* Override default if http "Connection:" header: */
252 if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
253 lws_hdr_copy(wsi, http_conn_str, sizeof(http_conn_str) - 1,
254 WSI_TOKEN_CONNECTION);
255 http_conn_str[sizeof(http_conn_str) - 1] = '\0';
256 if (!strcasecmp(http_conn_str, "keep-alive"))
257 connection_type = HTTP_CONNECTION_KEEP_ALIVE;
258 else
259 if (strcasecmp(http_conn_str, "close"))
260 connection_type = HTTP_CONNECTION_CLOSE;
261 }
262 wsi->u.http.connection_type = connection_type;
263
264 n = 0;
265 if (wsi->protocol->callback)
266 n = wsi->protocol->callback(context, wsi,
267 LWS_CALLBACK_FILTER_HTTP_CONNECTION,
268 wsi->user_space, uri_ptr, uri_len);
269
270 if (!n) {
271 /*
272 * if there is content supposed to be coming,
273 * put a timeout on it having arrived
274 */
275 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
276 AWAITING_TIMEOUT);
277
278 if (wsi->protocol->callback)
279 n = wsi->protocol->callback(context, wsi,
280 LWS_CALLBACK_HTTP,
281 wsi->user_space, uri_ptr, uri_len);
282 }
283
284 /* now drop the header info we kept a pointer to */
285 if (wsi->u.http.ah)
286 free(wsi->u.http.ah);
287 /* not possible to continue to use past here */
288 wsi->u.http.ah = NULL;
289
290 if (n) {
291 lwsl_info("LWS_CALLBACK_HTTP closing\n");
292 return 1; /* struct ah ptr already nuked */ }
293
294 /*
295 * If we're not issuing a file, check for content_length or
296 * HTTP keep-alive. No keep-alive header allocation for
297 * ISSUING_FILE, as this uses HTTP/1.0.
298 *
299 * In any case, return 0 and let libwebsocket_read decide how to
300 * proceed based on state
301 */
302 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
303 /* Prepare to read body if we have a content length: */
304 if (wsi->u.http.content_length > 0)
305 wsi->state = WSI_STATE_HTTP_BODY;
306
307 return 0;
308
309bail_nuke_ah:
310 /* drop the header info */
311 if (wsi->u.hdr.ah) {
312 free(wsi->u.hdr.ah);
313 wsi->u.hdr.ah = NULL;
314 }
315
316 return 1;
317}
318
Andy Greenaad2eac2014-04-03 09:03:37 +0800319
320int lws_handshake_server(struct libwebsocket_context *context,
321 struct libwebsocket *wsi, unsigned char **buf, size_t len)
322{
323 struct allocated_headers *ah;
Andy Green024eb6c2014-10-08 12:00:53 +0800324 int protocol_len;
Andy Green7a8d86e2014-07-19 06:52:39 +0800325 char protocol_list[128];
326 char protocol_name[32];
Andy Green7a8d86e2014-07-19 06:52:39 +0800327 char *p;
328 int n, hit;
Andy Greenaad2eac2014-04-03 09:03:37 +0800329
330 /* LWS_CONNMODE_WS_SERVING */
331
332 while (len--) {
Andrew Canaday74b4a652014-06-29 00:25:19 -0400333 if (libwebsocket_parse(context, wsi, *(*buf)++)) {
Andy Greenaad2eac2014-04-03 09:03:37 +0800334 lwsl_info("libwebsocket_parse failed\n");
335 goto bail_nuke_ah;
336 }
337
338 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
339 continue;
340
341 lwsl_parser("libwebsocket_parse sees parsing complete\n");
342
343 wsi->mode = LWS_CONNMODE_PRE_WS_SERVING_ACCEPT;
344 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
345
346 /* is this websocket protocol or normal http 1.0? */
347
348 if (!lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE) ||
349 !lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
Andy Green024eb6c2014-10-08 12:00:53 +0800350
Andy Greenaad2eac2014-04-03 09:03:37 +0800351 ah = wsi->u.hdr.ah;
Andy Green024eb6c2014-10-08 12:00:53 +0800352
Andy Greenaad2eac2014-04-03 09:03:37 +0800353 /* union transition */
354 memset(&wsi->u, 0, sizeof(wsi->u));
355 wsi->mode = LWS_CONNMODE_HTTP_SERVING_ACCEPTED;
356 wsi->state = WSI_STATE_HTTP;
357 wsi->u.http.fd = LWS_INVALID_FILE;
358
359 /* expose it at the same offset as u.hdr */
360 wsi->u.http.ah = ah;
Andy Green024eb6c2014-10-08 12:00:53 +0800361
362 n = lws_http_action(context, wsi);
Andy Greenaad2eac2014-04-03 09:03:37 +0800363
Andy Green024eb6c2014-10-08 12:00:53 +0800364 return n;
Andy Greenaad2eac2014-04-03 09:03:37 +0800365 }
Andy Greenb08cb502014-09-30 16:33:56 +0800366
367 lwsl_err(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE));
Andy Greenaad2eac2014-04-03 09:03:37 +0800368
Andy Green2af58562014-09-30 08:15:49 +0800369 if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
370 "websocket"))
371 goto upgrade_ws;
Andy Green024eb6c2014-10-08 12:00:53 +0800372#ifdef LWS_USE_HTTP2
Andy Greena54f2322014-09-30 09:43:14 +0800373 if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
Andy Greenb08cb502014-09-30 16:33:56 +0800374 "h2c-14"))
Andy Greena54f2322014-09-30 09:43:14 +0800375 goto upgrade_h2c;
Andy Green024eb6c2014-10-08 12:00:53 +0800376#endif
Andy Green2af58562014-09-30 08:15:49 +0800377 /* dunno what he wanted to upgrade to */
378 goto bail_nuke_ah;
Andy Greena54f2322014-09-30 09:43:14 +0800379
Andy Green024eb6c2014-10-08 12:00:53 +0800380#ifdef LWS_USE_HTTP2
381upgrade_h2c:
382 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
383 lwsl_err("missing http2_settings\n");
Andy Greena54f2322014-09-30 09:43:14 +0800384 goto bail_nuke_ah;
385 }
386
Andy Green024eb6c2014-10-08 12:00:53 +0800387 lwsl_err("h2c upgrade...\n");
Andy Greena54f2322014-09-30 09:43:14 +0800388
Andy Green024eb6c2014-10-08 12:00:53 +0800389 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
390 /* convert the peer's HTTP-Settings */
391 n = lws_b64_decode_string(p, protocol_list, sizeof(protocol_list));
392 if (n < 0) {
393 lwsl_parser("HTTP2_SETTINGS too long\n");
394 return 1;
395 }
396
397 /* adopt the header info */
398
399 ah = wsi->u.hdr.ah;
Andy Greena54f2322014-09-30 09:43:14 +0800400
401 wsi->mode = LWS_CONNMODE_HTTP2_SERVING;
402
403 /* union transition */
404 memset(&wsi->u, 0, sizeof(wsi->u));
Andy Green2af58562014-09-30 08:15:49 +0800405
Andy Green024eb6c2014-10-08 12:00:53 +0800406 /* http2 union member has http union struct at start */
407 wsi->u.http.ah = ah;
408
409 lws_http2_init(&wsi->u.http2.peer_settings);
410 lws_http2_init(&wsi->u.http2.my_settings);
411
412 /* HTTP2 union */
413
414 lws_http2_interpret_settings_payload(&wsi->u.http2.peer_settings, (unsigned char *)protocol_list, n);
415
416 strcpy(protocol_list,
417 "HTTP/1.1 101 Switching Protocols\x0d\x0a"
418 "Connection: Upgrade\x0d\x0a"
419 "Upgrade: h2c\x0d\x0a\x0d\x0a");
420 n = lws_issue_raw(wsi, (unsigned char *)protocol_list,
421 strlen(protocol_list));
422 if (n != strlen(protocol_list)) {
423 lwsl_debug("http2 switch: ERROR writing to socket\n");
424 return 1;
425 }
426
427 wsi->state = WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE;
428
Andy Greena54f2322014-09-30 09:43:14 +0800429 return 0;
Andy Green024eb6c2014-10-08 12:00:53 +0800430#endif
Andy Greena54f2322014-09-30 09:43:14 +0800431
Andy Green2af58562014-09-30 08:15:49 +0800432upgrade_ws:
Andy Greenaad2eac2014-04-03 09:03:37 +0800433 if (!wsi->protocol)
434 lwsl_err("NULL protocol at libwebsocket_read\n");
435
436 /*
437 * It's websocket
438 *
Andy Green7a8d86e2014-07-19 06:52:39 +0800439 * Select the first protocol we support from the list
440 * the client sent us.
441 *
442 * Copy it to remove header fragmentation
Andy Greenaad2eac2014-04-03 09:03:37 +0800443 */
444
Andy Green7a8d86e2014-07-19 06:52:39 +0800445 if (lws_hdr_copy(wsi, protocol_list, sizeof(protocol_list) - 1,
446 WSI_TOKEN_PROTOCOL) < 0) {
447 lwsl_err("protocol list too long");
448 goto bail_nuke_ah;
449 }
Andy Greenaad2eac2014-04-03 09:03:37 +0800450
Andy Green7a8d86e2014-07-19 06:52:39 +0800451 protocol_len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
452 protocol_list[protocol_len] = '\0';
453 p = protocol_list;
454 hit = 0;
Andy Greenaad2eac2014-04-03 09:03:37 +0800455
Andy Green7a8d86e2014-07-19 06:52:39 +0800456 while (*p && !hit) {
457 n = 0;
458 while (n < sizeof(protocol_name) - 1 && *p && *p !=',')
459 protocol_name[n++] = *p++;
460 protocol_name[n] = '\0';
461 if (*p)
462 p++;
463
464 lwsl_info("checking %s\n", protocol_name);
465
466 n = 0;
467 while (context->protocols[n].callback) {
Andy Greenafa10d52014-08-11 09:11:57 +0800468 if (!wsi->protocol->name) {
469 n++;
Andy Green7a8d86e2014-07-19 06:52:39 +0800470 continue;
Andy Greenafa10d52014-08-11 09:11:57 +0800471 }
Andy Green7a8d86e2014-07-19 06:52:39 +0800472 if (!strcmp(context->protocols[n].name,
473 protocol_name)) {
474 lwsl_info("prot match %d\n", n);
475 wsi->protocol = &context->protocols[n];
476 hit = 1;
477 break;
478 }
479
480 n++;
481 }
Andy Greenaad2eac2014-04-03 09:03:37 +0800482 }
483
484 /* we didn't find a protocol he wanted? */
485
Andy Green7a8d86e2014-07-19 06:52:39 +0800486 if (!hit) {
Andy Greenaad2eac2014-04-03 09:03:37 +0800487 if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) ==
488 NULL) {
Andy Green7a8d86e2014-07-19 06:52:39 +0800489 /*
490 * some clients only have one protocol and
491 * do not sent the protocol list header...
492 * allow it and match to protocol 0
493 */
494 lwsl_info("defaulting to prot 0 handler\n");
Andy Greenaad2eac2014-04-03 09:03:37 +0800495 wsi->protocol = &context->protocols[0];
496 } else {
Andy Green7a8d86e2014-07-19 06:52:39 +0800497 lwsl_err("No protocol from list \"%s\" supported\n",
498 protocol_list);
Andy Greenaad2eac2014-04-03 09:03:37 +0800499 goto bail_nuke_ah;
500 }
501 }
502
503 /* allocate wsi->user storage */
504 if (libwebsocket_ensure_user_space(wsi))
505 goto bail_nuke_ah;
506
507 /*
508 * Give the user code a chance to study the request and
509 * have the opportunity to deny it
510 */
511
512 if ((wsi->protocol->callback)(wsi->protocol->owning_server, wsi,
513 LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
514 wsi->user_space,
515 lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
516 lwsl_warn("User code denied connection\n");
517 goto bail_nuke_ah;
518 }
519
520
521 /*
522 * Perform the handshake according to the protocol version the
523 * client announced
524 */
525
526 switch (wsi->ietf_spec_revision) {
527 case 13:
528 lwsl_parser("lws_parse calling handshake_04\n");
529 if (handshake_0405(context, wsi)) {
530 lwsl_info("hs0405 has failed the connection\n");
531 goto bail_nuke_ah;
532 }
533 break;
534
535 default:
536 lwsl_warn("Unknown client spec version %d\n",
537 wsi->ietf_spec_revision);
538 goto bail_nuke_ah;
539 }
540
541 /* drop the header info -- no bail_nuke_ah after this */
542
543 if (wsi->u.hdr.ah)
544 free(wsi->u.hdr.ah);
545
546 wsi->mode = LWS_CONNMODE_WS_SERVING;
547
548 /* union transition */
549 memset(&wsi->u, 0, sizeof(wsi->u));
Andy Greenaad2eac2014-04-03 09:03:37 +0800550
551 /*
552 * create the frame buffer for this connection according to the
553 * size mentioned in the protocol definition. If 0 there, use
554 * a big default for compatibility
555 */
556
557 n = wsi->protocol->rx_buffer_size;
558 if (!n)
559 n = LWS_MAX_SOCKET_IO_BUF;
560 n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
561 wsi->u.ws.rx_user_buffer = malloc(n);
562 if (!wsi->u.ws.rx_user_buffer) {
563 lwsl_err("Out of Mem allocating rx buffer %d\n", n);
564 return 1;
565 }
566 lwsl_info("Allocating RX buffer %d\n", n);
567
568 if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
569 lwsl_warn("Failed to set SNDBUF to %d", n);
570 return 1;
571 }
572
573 lwsl_parser("accepted v%02d connection\n",
574 wsi->ietf_spec_revision);
575 } /* while all chars are handled */
576
577 return 0;
578
579bail_nuke_ah:
580 /* drop the header info */
581 if (wsi->u.hdr.ah)
582 free(wsi->u.hdr.ah);
583 return 1;
584}
585
Andy Greena1ce6be2013-01-18 11:43:21 +0800586struct libwebsocket *
587libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
588{
589 struct libwebsocket *new_wsi;
Andy Greena1ce6be2013-01-18 11:43:21 +0800590
591 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
592 if (new_wsi == NULL) {
593 lwsl_err("Out of memory for new connection\n");
594 return NULL;
595 }
596
597 memset(new_wsi, 0, sizeof(struct libwebsocket));
Andy Greena1ce6be2013-01-18 11:43:21 +0800598 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
Andy Green024eb6c2014-10-08 12:00:53 +0800599 new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
Andy Greena1ce6be2013-01-18 11:43:21 +0800600
601 /* intialize the instance struct */
602
603 new_wsi->state = WSI_STATE_HTTP;
Andy Greena1ce6be2013-01-18 11:43:21 +0800604 new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
Andy Green224149a2013-02-11 21:43:41 +0800605 new_wsi->hdr_parsing_completed = 0;
Andy Greena1ce6be2013-01-18 11:43:21 +0800606
Andy Green16ab3182013-02-10 18:02:31 +0800607 if (lws_allocate_header_table(new_wsi)) {
608 free(new_wsi);
609 return NULL;
Andy Greena1ce6be2013-01-18 11:43:21 +0800610 }
611
612 /*
613 * these can only be set once the protocol is known
614 * we set an unestablished connection's protocol pointer
615 * to the start of the supported list, so it can look
616 * for matching ones during the handshake
617 */
618 new_wsi->protocol = context->protocols;
619 new_wsi->user_space = NULL;
Andy Greena1ce6be2013-01-18 11:43:21 +0800620 new_wsi->ietf_spec_revision = 0;
621
Andy Green76b6ea12014-02-15 19:25:50 +0800622 /*
623 * outermost create notification for wsi
624 * no user_space because no protocol selection
625 */
626 context->protocols[0].callback(context, new_wsi,
627 LWS_CALLBACK_WSI_CREATE, NULL, NULL, 0);
628
Andy Greena1ce6be2013-01-18 11:43:21 +0800629 return new_wsi;
630}
631
632int lws_server_socket_service(struct libwebsocket_context *context,
Patrick Gansterer73882e42014-03-29 08:25:58 +0100633 struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
Andy Greena1ce6be2013-01-18 11:43:21 +0800634{
Andy Greencdb9bf92014-04-12 10:07:02 +0800635 struct libwebsocket *new_wsi = NULL;
636 int accept_fd = 0;
Bob Robertsac049112013-04-25 09:16:30 +0800637 socklen_t clilen;
Andy Greena1ce6be2013-01-18 11:43:21 +0800638 struct sockaddr_in cli_addr;
639 int n;
Patrick Ganstererac49f1e2014-03-30 10:18:51 +0200640 int len;
Andy Greena1ce6be2013-01-18 11:43:21 +0800641
642 switch (wsi->mode) {
643
644 case LWS_CONNMODE_HTTP_SERVING:
Andy Green7cf6cb02013-05-19 14:04:10 +0800645 case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
Andy Green024eb6c2014-10-08 12:00:53 +0800646 case LWS_CONNMODE_HTTP2_SERVING:
Andy Greena1ce6be2013-01-18 11:43:21 +0800647
648 /* handle http headers coming in */
649
Andy Green2764eba2013-12-09 14:16:17 +0800650 /* pending truncated sends have uber priority */
651
Andrew Canadayaf8db352014-08-23 21:45:12 -0400652 if (wsi->truncated_send_len) {
Patrick Ganstererb47f87b2014-03-30 09:18:05 +0200653 if (pollfd->revents & LWS_POLLOUT)
Andy Greena1a24d22014-04-10 14:25:24 +0800654 if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
Andy Green2764eba2013-12-09 14:16:17 +0800655 wsi->truncated_send_offset,
Andy Greena1a24d22014-04-10 14:25:24 +0800656 wsi->truncated_send_len) < 0) {
657 lwsl_info("closing from socket service\n");
658 return -1;
659 }
Andy Green2764eba2013-12-09 14:16:17 +0800660 /*
661 * we can't afford to allow input processing send
662 * something new, so spin around he event loop until
663 * he doesn't have any partials
664 */
665 break;
666 }
667
Andy Greena1ce6be2013-01-18 11:43:21 +0800668 /* any incoming data ready? */
669
Patrick Ganstererb47f87b2014-03-30 09:18:05 +0200670 if (pollfd->revents & LWS_POLLIN) {
Andy Green1f5c9f02014-10-09 08:14:30 +0800671 len = lws_ssl_capable_read(context, wsi,
Andy Greenb5b23192013-02-11 17:13:32 +0800672 context->service_buffer,
Andy Green78f266a2014-04-05 16:48:48 +0100673 sizeof(context->service_buffer));
674 switch (len) {
675 case 0:
Andy Green224149a2013-02-11 21:43:41 +0800676 lwsl_info("lws_server_skt_srv: read 0 len\n");
677 /* lwsl_info(" state=%d\n", wsi->state); */
678 if (!wsi->hdr_parsing_completed)
679 free(wsi->u.hdr.ah);
Andy Green78f266a2014-04-05 16:48:48 +0100680 /* fallthru */
681 case LWS_SSL_CAPABLE_ERROR:
Andy Greenb5b23192013-02-11 17:13:32 +0800682 libwebsocket_close_and_free_session(
Andy Green78f266a2014-04-05 16:48:48 +0100683 context, wsi,
684 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800685 return 0;
Andy Green78f266a2014-04-05 16:48:48 +0100686 case LWS_SSL_CAPABLE_MORE_SERVICE:
Christian Schüldtfde93792014-10-09 08:37:12 +0800687 goto try_pollout;
Andy Greena1ce6be2013-01-18 11:43:21 +0800688 }
689
Andy Greena1a24d22014-04-10 14:25:24 +0800690 /* just ignore incoming if waiting for close */
691 if (wsi->state != WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
692
693 /* hm this may want to send (via HTTP callback for example) */
Andy Greena1a24d22014-04-10 14:25:24 +0800694 n = libwebsocket_read(context, wsi,
695 context->service_buffer, len);
696 if (n < 0)
697 /* we closed wsi */
698 return 0;
Andy Green2764eba2013-12-09 14:16:17 +0800699
Andy Greena1a24d22014-04-10 14:25:24 +0800700 /* hum he may have used up the writability above */
701 break;
702 }
Andy Greena1ce6be2013-01-18 11:43:21 +0800703 }
704
Christian Schüldtfde93792014-10-09 08:37:12 +0800705try_pollout:
Andy Greena1ce6be2013-01-18 11:43:21 +0800706 /* this handles POLLOUT for http serving fragments */
707
Patrick Ganstererb47f87b2014-03-30 09:18:05 +0200708 if (!(pollfd->revents & LWS_POLLOUT))
Andy Greena1ce6be2013-01-18 11:43:21 +0800709 break;
710
711 /* one shot */
Andy Green158e8042014-04-02 14:25:10 +0800712 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
713 goto fail;
Andy Greena717df22014-04-11 13:14:37 +0800714
715 lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
Andy Green7a132792013-12-18 09:48:26 +0800716
Andy Green54cb3462013-02-14 22:23:54 +0800717 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
718 n = user_callback_handle_rxflow(
719 wsi->protocol->callback,
720 wsi->protocol->owning_server,
721 wsi, LWS_CALLBACK_HTTP_WRITEABLE,
722 wsi->user_space,
723 NULL,
724 0);
725 if (n < 0)
726 libwebsocket_close_and_free_session(
727 context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800728 break;
Andy Green54cb3462013-02-14 22:23:54 +0800729 }
Andy Greena1ce6be2013-01-18 11:43:21 +0800730
Andy Greenb5b23192013-02-11 17:13:32 +0800731 /* nonzero for completion or error */
732 if (libwebsockets_serve_http_file_fragment(context, wsi))
Andy Greena1ce6be2013-01-18 11:43:21 +0800733 libwebsocket_close_and_free_session(context, wsi,
734 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena1ce6be2013-01-18 11:43:21 +0800735 break;
736
737 case LWS_CONNMODE_SERVER_LISTENER:
738
739 /* pollin means a client has connected to us then */
740
Patrick Ganstererb47f87b2014-03-30 09:18:05 +0200741 if (!(pollfd->revents & LWS_POLLIN))
Andy Greena1ce6be2013-01-18 11:43:21 +0800742 break;
743
744 /* listen socket got an unencrypted connection... */
745
746 clilen = sizeof(cli_addr);
Andy Greene000a702013-01-29 12:37:35 +0800747 lws_latency_pre(context, wsi);
Andy Greena1ce6be2013-01-18 11:43:21 +0800748 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
749 &clilen);
Andy Greenb5b23192013-02-11 17:13:32 +0800750 lws_latency(context, wsi,
751 "unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
752 accept_fd, accept_fd >= 0);
Andy Greena1ce6be2013-01-18 11:43:21 +0800753 if (accept_fd < 0) {
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100754 if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK) {
Andy Greene2160712013-01-28 12:19:10 +0800755 lwsl_debug("accept asks to try again\n");
756 break;
757 }
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100758 lwsl_warn("ERROR on accept: %s\n", strerror(LWS_ERRNO));
Andy Greena1ce6be2013-01-18 11:43:21 +0800759 break;
760 }
761
Andy Green158e8042014-04-02 14:25:10 +0800762 lws_plat_set_socket_options(context, accept_fd);
Andy Green6f047ee2013-01-28 11:23:52 +0800763
Andy Greena1ce6be2013-01-18 11:43:21 +0800764 /*
765 * look at who we connected to and give user code a chance
766 * to reject based on client IP. There's no protocol selected
767 * yet so we issue this to protocols[0]
768 */
769
770 if ((context->protocols[0].callback)(context, wsi,
771 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Edwin van den Oetelaar8c8a8e12013-02-20 20:56:59 +0800772 NULL, (void *)(long)accept_fd, 0)) {
Andy Greena1ce6be2013-01-18 11:43:21 +0800773 lwsl_debug("Callback denied network connection\n");
774 compatible_close(accept_fd);
775 break;
776 }
777
778 new_wsi = libwebsocket_create_new_server_wsi(context);
779 if (new_wsi == NULL) {
780 compatible_close(accept_fd);
781 break;
782 }
783
784 new_wsi->sock = accept_fd;
785
Andy Green176de272014-02-15 14:36:02 +0800786 /* the transport is accepted... give him time to negotiate */
787 libwebsocket_set_timeout(new_wsi,
788 PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
789 AWAITING_TIMEOUT);
790
Alexandre Erwin Ittnerd578f572014-02-06 23:15:51 -0200791 /*
792 * A new connection was accepted. Give the user a chance to
793 * set properties of the newly created wsi. There's no protocol
794 * selected yet so we issue this to protocols[0]
795 */
796
797 (context->protocols[0].callback)(context, new_wsi,
798 LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0);
799
Andy Greena717df22014-04-11 13:14:37 +0800800 lws_libev_accept(context, new_wsi, accept_fd);
Alexandre Erwin Ittnerd578f572014-02-06 23:15:51 -0200801
Andy Greencdb9bf92014-04-12 10:07:02 +0800802 if (!LWS_SSL_ENABLED(context)) {
Andy Greena1ce6be2013-01-18 11:43:21 +0800803 lwsl_debug("accepted new conn port %u on fd=%d\n",
804 ntohs(cli_addr.sin_port), accept_fd);
805
Andy Greene2160712013-01-28 12:19:10 +0800806 insert_wsi_socket_into_fds(context, new_wsi);
Andy Greene2160712013-01-28 12:19:10 +0800807 }
Andy Greena1ce6be2013-01-18 11:43:21 +0800808 break;
Andy Greene2160712013-01-28 12:19:10 +0800809
Andy Greena1ce6be2013-01-18 11:43:21 +0800810 default:
811 break;
812 }
Andy Greencdb9bf92014-04-12 10:07:02 +0800813
Andy Green62824f92014-08-10 09:50:42 +0800814 if (lws_server_socket_service_ssl(context, &wsi, new_wsi,
815 accept_fd, pollfd))
816 goto fail;
Andy Greencdb9bf92014-04-12 10:07:02 +0800817
Andy Greena1ce6be2013-01-18 11:43:21 +0800818 return 0;
Andy Green158e8042014-04-02 14:25:10 +0800819
820fail:
821 libwebsocket_close_and_free_session(context, wsi,
822 LWS_CLOSE_STATUS_NOSTATUS);
823 return 1;
Andy Greena1ce6be2013-01-18 11:43:21 +0800824}
Joakim Soderberg63ff1202013-02-11 17:52:23 +0100825
Andy Green4e7a1332013-11-11 07:30:33 +0800826
827static const char *err400[] = {
828 "Bad Request",
829 "Unauthorized",
830 "Payment Required",
831 "Forbidden",
832 "Not Found",
833 "Method Not Allowed",
834 "Not Acceptable",
835 "Proxy Auth Required",
836 "Request Timeout",
837 "Conflict",
838 "Gone",
839 "Length Required",
840 "Precondition Failed",
841 "Request Entity Too Large",
842 "Request URI too Long",
843 "Unsupported Media Type",
844 "Requested Range Not Satisfiable",
845 "Expectation Failed"
846};
847
848static const char *err500[] = {
849 "Internal Server Error",
850 "Not Implemented",
851 "Bad Gateway",
852 "Service Unavailable",
853 "Gateway Timeout",
854 "HTTP Version Not Supported"
855};
856
857/**
858 * libwebsockets_return_http_status() - Return simple http status
859 * @context: libwebsockets context
860 * @wsi: Websocket instance (available from user callback)
861 * @code: Status index, eg, 404
862 * @html_body: User-readable HTML description, or NULL
863 *
864 * Helper to report HTTP errors back to the client cleanly and
865 * consistently
866 */
Andy Green83725d82014-02-27 07:19:21 +0800867LWS_VISIBLE int libwebsockets_return_http_status(
Andy Green4e7a1332013-11-11 07:30:33 +0800868 struct libwebsocket_context *context, struct libwebsocket *wsi,
869 unsigned int code, const char *html_body)
870{
871 int n, m;
872 const char *description = "";
873
874 if (!html_body)
875 html_body = "";
876
877 if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
878 description = err400[code - 400];
879 if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
880 description = err500[code - 500];
881
Andy Green024eb6c2014-10-08 12:00:53 +0800882 n = sprintf((char *)context->service_buffer +
883 LWS_SEND_BUFFER_PRE_PADDING,
Andy Green4e7a1332013-11-11 07:30:33 +0800884 "HTTP/1.0 %u %s\x0d\x0a"
885 "Server: libwebsockets\x0d\x0a"
Patrick Ganstererfce64cd2014-02-27 11:42:41 +0100886 "Content-Type: text/html\x0d\x0a\x0d\x0a"
Andy Green4e7a1332013-11-11 07:30:33 +0800887 "<h1>%u %s</h1>%s",
888 code, description, code, description, html_body);
889
Andy Green07631f42014-10-10 06:13:40 +0800890 lwsl_info((const char *)context->service_buffer +
891 LWS_SEND_BUFFER_PRE_PADDING);
Andy Green4e7a1332013-11-11 07:30:33 +0800892
Andy Green07631f42014-10-10 06:13:40 +0800893 m = libwebsocket_write(wsi, context->service_buffer +
894 LWS_SEND_BUFFER_PRE_PADDING, n,
Andy Green024eb6c2014-10-08 12:00:53 +0800895 LWS_WRITE_HTTP_HEADERS);
Andy Green4e7a1332013-11-11 07:30:33 +0800896
897 return m;
898}
899
900/**
901 * libwebsockets_serve_http_file() - Send a file back to the client using http
902 * @context: libwebsockets context
903 * @wsi: Websocket instance (available from user callback)
904 * @file: The file to issue over http
905 * @content_type: The http content type, eg, text/html
906 * @other_headers: NULL or pointer to \0-terminated other header string
907 *
908 * This function is intended to be called from the callback in response
909 * to http requests from the client. It allows the callback to issue
910 * local files down the http link in a single step.
911 *
912 * Returning <0 indicates error and the wsi should be closed. Returning
913 * >0 indicates the file was completely sent and the wsi should be closed.
914 * ==0 indicates the file transfer is started and needs more service later,
915 * the wsi should be left alone.
916 */
917
918LWS_VISIBLE int libwebsockets_serve_http_file(
919 struct libwebsocket_context *context,
920 struct libwebsocket *wsi, const char *file,
921 const char *content_type, const char *other_headers)
922{
Andy Green024eb6c2014-10-08 12:00:53 +0800923 unsigned char *response = context->service_buffer + LWS_SEND_BUFFER_PRE_PADDING;
924 unsigned char *p = response;
Andy Green4e7a1332013-11-11 07:30:33 +0800925 int ret = 0;
926 int n;
927
Andy Green158e8042014-04-02 14:25:10 +0800928 wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen);
Andy Green4e7a1332013-11-11 07:30:33 +0800929
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100930 if (wsi->u.http.fd == LWS_INVALID_FILE) {
Andy Green4e7a1332013-11-11 07:30:33 +0800931 lwsl_err("Unable to open '%s'\n", file);
932 libwebsockets_return_http_status(context, wsi,
933 HTTP_STATUS_NOT_FOUND, NULL);
Andy Green4e7a1332013-11-11 07:30:33 +0800934 return -1;
935 }
936
Andy Green024eb6c2014-10-08 12:00:53 +0800937 p += sprintf((char *)p, "HTTP/1.0 200 OK\x0d\x0a"
938 "Server: libwebsockets\x0d\x0a"
939 "Content-Type: %s\x0d\x0a", content_type);
Andy Green4e7a1332013-11-11 07:30:33 +0800940 if (other_headers) {
941 n = strlen(other_headers);
942 memcpy(p, other_headers, n);
943 p += n;
944 }
945 p += sprintf((char *)p,
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100946 "Content-Length: %lu\x0d\x0a\x0d\x0a", wsi->u.http.filelen);
Andy Green4e7a1332013-11-11 07:30:33 +0800947
Andy Green024eb6c2014-10-08 12:00:53 +0800948 ret = libwebsocket_write(wsi, response,
949 p - response, LWS_WRITE_HTTP_HEADERS);
950 if (ret != (p - response)) {
951 lwsl_err("_write returned %d from %d\n", ret, (p - response));
Andy Green4e7a1332013-11-11 07:30:33 +0800952 return -1;
953 }
954
955 wsi->u.http.filepos = 0;
956 wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
957
958 return libwebsockets_serve_http_file_fragment(context, wsi);
959}
960
Andy Greend7340c12014-04-10 14:08:10 +0800961
962int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
963 unsigned char *buf, size_t len)
964{
965 size_t n = 0;
966 int m;
967
968#if 0
969 lwsl_parser("received %d byte packet\n", (int)len);
970 lwsl_hexdump(buf, len);
971#endif
972
973 /* let the rx protocol state machine have as much as it needs */
974
975 while (n < len) {
976 /*
977 * we were accepting input but now we stopped doing so
978 */
Andy Green024eb6c2014-10-08 12:00:53 +0800979 if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
980 lws_rxflow_cache(wsi, buf, n, len);
Andy Greend7340c12014-04-10 14:08:10 +0800981
982 return 1;
983 }
984
985 /* account for what we're using in rxflow buffer */
Andy Green024eb6c2014-10-08 12:00:53 +0800986 if (wsi->rxflow_buffer)
987 wsi->rxflow_pos++;
Andy Greend7340c12014-04-10 14:08:10 +0800988
989 /* process the byte */
990 m = libwebsocket_rx_sm(wsi, buf[n++]);
991 if (m < 0)
992 return -1;
993 }
994
995 return 0;
Andy Greencdb9bf92014-04-12 10:07:02 +0800996}
997
998LWS_VISIBLE void
999lws_server_get_canonical_hostname(struct libwebsocket_context *context,
1000 struct lws_context_creation_info *info)
1001{
1002 if (info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)
1003 return;
1004
1005 /* find canonical hostname */
1006 gethostname((char *)context->canonical_hostname,
1007 sizeof(context->canonical_hostname) - 1);
1008
1009 lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
vpeter44dd8ada2014-04-27 13:28:22 +02001010}