blob: 6148ba5473ce4b1d4ffd99805f28886b743524c0 [file] [log] [blame]
Andy Green7c212cc2010-11-08 20:20:42 +00001/*
2 * libwebsockets - small server side websockets and web server implementation
Andy Greene77ddd82010-11-13 10:03:47 +00003 *
Andy Green1cc03882015-12-06 08:00:03 +08004 * Copyright (C) 2010-2015 Andy Green <andy@warmcat.com>
Andy Green7c212cc2010-11-08 20:20:42 +00005 *
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#include "private-libwebsockets.h"
23
Andy Green7c212cc2010-11-08 20:20:42 +000024/*
Andy Greend1b11e32011-01-18 15:39:02 +000025 * -04 of the protocol (actually the 80th version) has a radically different
26 * handshake. The 04 spec gives the following idea
27 *
28 * The handshake from the client looks as follows:
29 *
30 * GET /chat HTTP/1.1
31 * Host: server.example.com
32 * Upgrade: websocket
33 * Connection: Upgrade
34 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
35 * Sec-WebSocket-Origin: http://example.com
36 * Sec-WebSocket-Protocol: chat, superchat
Andy Greene2522172011-01-18 17:14:03 +000037 * Sec-WebSocket-Version: 4
Andy Greend1b11e32011-01-18 15:39:02 +000038 *
39 * The handshake from the server looks as follows:
40 *
41 * HTTP/1.1 101 Switching Protocols
42 * Upgrade: websocket
43 * Connection: Upgrade
44 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
45 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
46 * Sec-WebSocket-Protocol: chat
47 */
48
Andrew Canadayafe26cf2014-07-13 01:07:36 -040049#ifndef min
50#define min(a, b) ((a) < (b) ? (a) : (b))
51#endif
Andy Green1cc03882015-12-06 08:00:03 +080052
Andy Greend1b11e32011-01-18 15:39:02 +000053/*
Andy Green7c212cc2010-11-08 20:20:42 +000054 * We have to take care about parsing because the headers may be split
55 * into multiple fragments. They may contain unknown headers with arbitrary
56 * argument lengths. So, we parse using a single-character at a time state
57 * machine that is completely independent of packet size.
Andy Green2c218e72016-02-15 12:37:04 +080058 *
59 * Returns <0 for error or length of chars consumed from buf (up to len)
Andy Green7c212cc2010-11-08 20:20:42 +000060 */
61
Peter Pentchev9a4fef72013-03-30 09:52:21 +080062LWS_VISIBLE int
Andy Green11c05bf2015-12-16 18:19:08 +080063lws_read(struct lws *wsi, unsigned char *buf, size_t len)
Andy Green7c212cc2010-11-08 20:20:42 +000064{
Andy Green2c218e72016-02-15 12:37:04 +080065 unsigned char *last_char, *oldbuf = buf;
Andy Green1cc03882015-12-06 08:00:03 +080066 int body_chunk_len;
67 size_t n;
Andy Greene77ddd82010-11-13 10:03:47 +000068
Andy Green67112662016-01-11 11:34:01 +080069 lwsl_debug("%s: incoming len %d\n", __func__, (int)len);
70
Andy Green7c212cc2010-11-08 20:20:42 +000071 switch (wsi->state) {
Andy Green095d3032014-10-08 12:15:15 +080072#ifdef LWS_USE_HTTP2
Andy Green54806b12015-12-17 17:03:59 +080073 case LWSS_HTTP2_AWAIT_CLIENT_PREFACE:
74 case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS:
75 case LWSS_HTTP2_ESTABLISHED:
Andy Green024eb6c2014-10-08 12:00:53 +080076 n = 0;
77 while (n < len) {
78 /*
79 * we were accepting input but now we stopped doing so
80 */
81 if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
82 lws_rxflow_cache(wsi, buf, n, len);
83
84 return 1;
85 }
86
87 /* account for what we're using in rxflow buffer */
88 if (wsi->rxflow_buffer)
89 wsi->rxflow_pos++;
Andy Green11c05bf2015-12-16 18:19:08 +080090 if (lws_http2_parser(wsi, buf[n++]))
Andy Green024eb6c2014-10-08 12:00:53 +080091 goto bail;
92 }
93 break;
Andy Green095d3032014-10-08 12:15:15 +080094#endif
Andy Green2c218e72016-02-15 12:37:04 +080095
Andy Green54806b12015-12-17 17:03:59 +080096 case LWSS_HTTP:
Andrew Canadaye9173452014-08-06 08:58:23 -040097 wsi->hdr_parsing_completed = 0;
98 /* fallthru */
Andy Green54806b12015-12-17 17:03:59 +080099 case LWSS_HTTP_ISSUING_FILE:
100 wsi->state = LWSS_HTTP_HEADERS;
Andy Green623a98d2013-01-21 11:04:23 +0800101 wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
102 wsi->u.hdr.lextable_pos = 0;
Andy Green7c212cc2010-11-08 20:20:42 +0000103 /* fallthru */
Andy Green54806b12015-12-17 17:03:59 +0800104 case LWSS_HTTP_HEADERS:
Andy Green8c1f6022016-01-26 20:56:56 +0800105 assert(wsi->u.hdr.ah);
Andy Green43db0452013-01-10 19:50:35 +0800106 lwsl_parser("issuing %d bytes to parser\n", (int)len);
Andy Green4739e5c2011-01-22 12:51:57 +0000107
Andy Greenaad2eac2014-04-03 09:03:37 +0800108 if (lws_handshake_client(wsi, &buf, len))
109 goto bail;
110
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400111 last_char = buf;
Andy Green11c05bf2015-12-16 18:19:08 +0800112 if (lws_handshake_server(wsi, &buf, len))
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400113 /* Handshake indicates this session is done. */
114 goto bail;
115
Andy Green44e0b082015-12-28 14:24:49 +0800116 /*
117 * It's possible that we've exhausted our data already, or
118 * rx flow control has stopped us dealing with this early,
119 * but lws_handshake_server doesn't update len for us.
Andy Green54806b12015-12-17 17:03:59 +0800120 * Figure out how much was read, so that we can proceed
121 * appropriately:
122 */
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400123 len -= (buf - last_char);
Andy Green44e0b082015-12-28 14:24:49 +0800124 lwsl_debug("%s: thinks we have used %d\n", __func__, len);
Andrew Canadayc7dbad62014-07-19 07:00:52 +0800125
126 if (!wsi->hdr_parsing_completed)
127 /* More header content on the way */
128 goto read_ok;
129
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400130 switch (wsi->state) {
Andy Green54806b12015-12-17 17:03:59 +0800131 case LWSS_HTTP:
132 case LWSS_HTTP_HEADERS:
Andy Greendbfbbb42016-02-24 20:58:19 +0800133 goto read_ok;
Andy Green54806b12015-12-17 17:03:59 +0800134 case LWSS_HTTP_ISSUING_FILE:
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400135 goto read_ok;
Andy Green54806b12015-12-17 17:03:59 +0800136 case LWSS_HTTP_BODY:
Andy Green6ab6ee22015-12-06 06:39:51 +0800137 wsi->u.http.content_remain =
138 wsi->u.http.content_length;
139 if (wsi->u.http.content_remain)
140 goto http_postbody;
141
142 /* there is no POST content */
143 goto postbody_completion;
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400144 default:
145 break;
146 }
147 break;
148
Andy Green54806b12015-12-17 17:03:59 +0800149 case LWSS_HTTP_BODY:
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400150http_postbody:
151 while (len && wsi->u.http.content_remain) {
152 /* Copy as much as possible, up to the limit of:
153 * what we have in the read buffer (len)
154 * remaining portion of the POST body (content_remain)
155 */
156 body_chunk_len = min(wsi->u.http.content_remain,len);
157 wsi->u.http.content_remain -= body_chunk_len;
158 len -= body_chunk_len;
Andy Green6a8099b2016-02-21 21:25:48 +0800159#ifdef LWS_WITH_CGI
160 if (wsi->cgi) {
161 struct lws_cgi_args args;
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400162
Andy Green6a8099b2016-02-21 21:25:48 +0800163 args.ch = LWS_STDIN;
164 args.stdwsi = &wsi->cgi->stdwsi[0];
165 args.data = buf;
166 args.len = body_chunk_len;
Andy Green6ab6ee22015-12-06 06:39:51 +0800167
Andy Green6a8099b2016-02-21 21:25:48 +0800168 /* returns how much used */
169 n = user_callback_handle_rxflow(
170 wsi->protocol->callback,
171 wsi, LWS_CALLBACK_CGI_STDIN_DATA,
172 wsi->user_space,
173 (void *)&args, 0);
174 if (n < 0)
175 goto bail;
176 } else {
177#endif
178 n = wsi->protocol->callback(wsi,
179 LWS_CALLBACK_HTTP_BODY, wsi->user_space,
180 buf, body_chunk_len);
181 if (n)
182 goto bail;
183 n = body_chunk_len;
184#ifdef LWS_WITH_CGI
185 }
186#endif
187 buf += n;
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400188
Andy Green6ab6ee22015-12-06 06:39:51 +0800189 if (wsi->u.http.content_remain) {
190 lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
Andy Green200a6a22016-02-15 20:36:02 +0800191 wsi->context->timeout_secs);
Andy Green6ab6ee22015-12-06 06:39:51 +0800192 break;
193 }
194 /* he sent all the content in time */
195postbody_completion:
196 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
Andy Green6a8099b2016-02-21 21:25:48 +0800197#ifdef LWS_WITH_CGI
198 if (!wsi->cgi)
199#endif
200 {
201 n = wsi->protocol->callback(wsi,
202 LWS_CALLBACK_HTTP_BODY_COMPLETION,
203 wsi->user_space, NULL, 0);
204 if (n)
205 goto bail;
206 }
Andy Green6ab6ee22015-12-06 06:39:51 +0800207
208 goto http_complete;
Andy Green4739e5c2011-01-22 12:51:57 +0000209 }
Andy Green7c212cc2010-11-08 20:20:42 +0000210 break;
211
Andy Green54806b12015-12-17 17:03:59 +0800212 case LWSS_ESTABLISHED:
213 case LWSS_AWAITING_CLOSE_ACK:
Andy Green8c1f6022016-01-26 20:56:56 +0800214 case LWSS_SHUTDOWN:
Andy Greend7340c12014-04-10 14:08:10 +0800215 if (lws_handshake_client(wsi, &buf, len))
216 goto bail;
Andy Greenf3d3b402011-02-09 07:16:34 +0000217 switch (wsi->mode) {
Andy Green54806b12015-12-17 17:03:59 +0800218 case LWSCM_WS_SERVING:
Andy Green4739e5c2011-01-22 12:51:57 +0000219
Andy Green67112662016-01-11 11:34:01 +0800220 if (lws_interpret_incoming_packet(wsi, &buf, len) < 0) {
Andy Greend7340c12014-04-10 14:08:10 +0800221 lwsl_info("interpret_incoming_packet has bailed\n");
222 goto bail;
223 }
Andy Greenf3d3b402011-02-09 07:16:34 +0000224 break;
Andy Green4739e5c2011-01-22 12:51:57 +0000225 }
Andy Green7c212cc2010-11-08 20:20:42 +0000226 break;
227 default:
Andy Green11c05bf2015-12-16 18:19:08 +0800228 lwsl_err("%s: Unhandled state\n", __func__);
Andy Green7c212cc2010-11-08 20:20:42 +0000229 break;
230 }
Andy Greene77ddd82010-11-13 10:03:47 +0000231
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400232read_ok:
Andy Green6ab6ee22015-12-06 06:39:51 +0800233 /* Nothing more to do for now */
Andy Green2c218e72016-02-15 12:37:04 +0800234 lwsl_info("%s: read_ok, used %d\n", __func__, buf - oldbuf);
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400235
Andy Green2c218e72016-02-15 12:37:04 +0800236 return buf - oldbuf;
Andy Greene77ddd82010-11-13 10:03:47 +0000237
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400238http_complete:
Andy Green11c05bf2015-12-16 18:19:08 +0800239 lwsl_debug("%s: http_complete\n", __func__);
Carl Stehle66d466a2014-08-16 10:17:59 +0800240
Andy Green2721e3c2015-10-21 09:23:21 +0800241#ifndef LWS_NO_SERVER
Carl Stehle66d466a2014-08-16 10:17:59 +0800242 /* Did the client want to keep the HTTP connection going? */
Andy Green26271482015-10-21 08:16:34 +0800243 if (lws_http_transaction_completed(wsi))
244 goto bail;
Andy Green2721e3c2015-10-21 09:23:21 +0800245#endif
Andy Green2c218e72016-02-15 12:37:04 +0800246 /* we may have next header set already, but return to event loop first
247 * so a heaily-pipelined http/1.1 connection cannot monopolize the
248 * service thread with GET hugefile.bin GET hugefile.bin etc
249 */
250 goto read_ok;
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400251
Andy Green7c212cc2010-11-08 20:20:42 +0000252bail:
Andy Green62304762015-12-04 08:43:54 +0800253 lwsl_debug("closing connection at lws_read bail:\n");
Andy Green6b5de702015-12-15 21:15:58 +0800254 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green6964bb52011-01-23 16:50:33 +0000255
Andy Green7c212cc2010-11-08 20:20:42 +0000256 return -1;
257}