2010-11-08 20:20:42 +00:00
|
|
|
/*
|
|
|
|
* libwebsockets - small server side websockets and web server implementation
|
2010-11-13 10:03:47 +00:00
|
|
|
*
|
2017-09-23 12:55:21 +08:00
|
|
|
* Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
|
2010-11-08 20:20:42 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation:
|
|
|
|
* version 2.1 of the License.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "private-libwebsockets.h"
|
|
|
|
|
2011-01-18 15:39:02 +00:00
|
|
|
/*
|
|
|
|
* -04 of the protocol (actually the 80th version) has a radically different
|
|
|
|
* handshake. The 04 spec gives the following idea
|
|
|
|
*
|
|
|
|
* The handshake from the client looks as follows:
|
|
|
|
*
|
|
|
|
* GET /chat HTTP/1.1
|
|
|
|
* Host: server.example.com
|
|
|
|
* Upgrade: websocket
|
|
|
|
* Connection: Upgrade
|
|
|
|
* Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
|
|
|
|
* Sec-WebSocket-Origin: http://example.com
|
|
|
|
* Sec-WebSocket-Protocol: chat, superchat
|
2011-01-18 17:14:03 +00:00
|
|
|
* Sec-WebSocket-Version: 4
|
2011-01-18 15:39:02 +00:00
|
|
|
*
|
|
|
|
* The handshake from the server looks as follows:
|
|
|
|
*
|
|
|
|
* HTTP/1.1 101 Switching Protocols
|
|
|
|
* Upgrade: websocket
|
|
|
|
* Connection: Upgrade
|
|
|
|
* Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
|
|
|
|
* Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
|
|
|
|
* Sec-WebSocket-Protocol: chat
|
|
|
|
*/
|
|
|
|
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
#ifndef min
|
|
|
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
|
|
#endif
|
2015-12-06 08:00:03 +08:00
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
/*
|
|
|
|
* We have to take care about parsing because the headers may be split
|
|
|
|
* into multiple fragments. They may contain unknown headers with arbitrary
|
|
|
|
* argument lengths. So, we parse using a single-character at a time state
|
|
|
|
* machine that is completely independent of packet size.
|
ah owns rxbuf
This is intended to solve a longstanding problem with the
relationship between http/1.1 keep-alive and the service
loop.
Ah now contain an rx buffer which is used during header
processing, and the ah may not be detached from the wsi
until the rx buffer is exhausted.
Having the rx buffer in the ah means we can delay using the
rx until a later service loop.
Ah which have pending rx force POLLIN service on the wsi
they are attached to automatically, so we can interleave
general service / connections with draining each ah rx
buffer.
The possible http/1.1 situations and their dispositions are:
1) exactly one set of http headers come. After processing,
the ah is detached since no pending rx left. If more
headers come later, a fresh ah is aqcuired when available
and the rx flow control blocks the read until then.
2) more that one whole set of headers come and we remain in
http mode (no upgrade). The ah is left attached and
returns to the service loop after the first set of headers.
We will get forced service due to the ah having pending
content (respecting flowcontrol) and process the pending
rx in the ah. If we use it all up, we will detach the
ah.
3) one set of http headers come with ws traffic appended.
We service the headers, do the upgrade, and keep the ah
until the remaining ws content is used. When we
exhausted the ws traffix in the ah rx buffer, we
detach the ah.
Since there can be any amount of http/1.1 pipelining on a
connection, and each may be expensive to service, it's now
enforced there is a return to the service loop after each
header set is serviced on a connection.
When I added the forced service for ah with pending buffering,
I added support for it to the windows plat code. However this
is untested.
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-02-15 12:37:04 +08:00
|
|
|
*
|
|
|
|
* Returns <0 for error or length of chars consumed from buf (up to len)
|
2010-11-08 20:20:42 +00:00
|
|
|
*/
|
|
|
|
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE int
|
2017-06-09 20:20:42 +08:00
|
|
|
lws_read(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
|
2010-11-08 20:20:42 +00:00
|
|
|
{
|
ah owns rxbuf
This is intended to solve a longstanding problem with the
relationship between http/1.1 keep-alive and the service
loop.
Ah now contain an rx buffer which is used during header
processing, and the ah may not be detached from the wsi
until the rx buffer is exhausted.
Having the rx buffer in the ah means we can delay using the
rx until a later service loop.
Ah which have pending rx force POLLIN service on the wsi
they are attached to automatically, so we can interleave
general service / connections with draining each ah rx
buffer.
The possible http/1.1 situations and their dispositions are:
1) exactly one set of http headers come. After processing,
the ah is detached since no pending rx left. If more
headers come later, a fresh ah is aqcuired when available
and the rx flow control blocks the read until then.
2) more that one whole set of headers come and we remain in
http mode (no upgrade). The ah is left attached and
returns to the service loop after the first set of headers.
We will get forced service due to the ah having pending
content (respecting flowcontrol) and process the pending
rx in the ah. If we use it all up, we will detach the
ah.
3) one set of http headers come with ws traffic appended.
We service the headers, do the upgrade, and keep the ah
until the remaining ws content is used. When we
exhausted the ws traffix in the ah rx buffer, we
detach the ah.
Since there can be any amount of http/1.1 pipelining on a
connection, and each may be expensive to service, it's now
enforced there is a return to the service loop after each
header set is serviced on a connection.
When I added the forced service for ah with pending buffering,
I added support for it to the windows plat code. However this
is untested.
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-02-15 12:37:04 +08:00
|
|
|
unsigned char *last_char, *oldbuf = buf;
|
2017-11-24 10:54:59 +08:00
|
|
|
lws_filepos_t body_chunk_len;
|
2015-12-06 08:00:03 +08:00
|
|
|
size_t n;
|
2010-11-13 10:03:47 +00:00
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
switch (wsi->state) {
|
2017-09-28 11:29:03 +08:00
|
|
|
#ifdef LWS_WITH_HTTP2
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP2_AWAIT_CLIENT_PREFACE:
|
|
|
|
case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS:
|
|
|
|
case LWSS_HTTP2_ESTABLISHED:
|
2017-10-13 10:33:02 +08:00
|
|
|
/*
|
|
|
|
* wsi here is always the network connection wsi, not a stream
|
2017-11-14 07:35:05 +08:00
|
|
|
* wsi. Once we unpicked the framing we will find the right
|
|
|
|
* swsi and make it the target of the frame.
|
|
|
|
*
|
|
|
|
* If it's ws over h2, the nwsi will get us here to do the h2
|
|
|
|
* processing, and that will call us back with the swsi +
|
|
|
|
* ESTABLISHED state for the inner payload, handled in a later
|
|
|
|
* case.
|
2017-10-13 10:33:02 +08:00
|
|
|
*/
|
2017-11-25 10:10:33 +08:00
|
|
|
while (len) {
|
2014-10-08 12:00:53 +08:00
|
|
|
/*
|
|
|
|
* we were accepting input but now we stopped doing so
|
|
|
|
*/
|
2017-10-13 10:33:02 +08:00
|
|
|
if (lws_is_flowcontrolled(wsi)) {
|
2017-11-25 10:10:33 +08:00
|
|
|
lws_rxflow_cache(wsi, buf, 0, (int)len);
|
2014-10-08 12:00:53 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-12-07 07:20:47 +08:00
|
|
|
/*
|
|
|
|
* lws_h2_parser() may send something; when it gets the
|
|
|
|
* whole frame, it will want to perform some action
|
|
|
|
* involving a reply. But we may be in a partial send
|
|
|
|
* situation on the network wsi...
|
|
|
|
*
|
|
|
|
* Even though we may be in a partial send and unable to
|
|
|
|
* send anything new, we still have to parse the network
|
|
|
|
* wsi in order to gain tx credit to send, which is
|
|
|
|
* potentially necessary to clear the old partial send.
|
|
|
|
*
|
|
|
|
* ALL network wsi-specific frames are sent by PPS
|
|
|
|
* already, these are sent as a priority on the writable
|
|
|
|
* handler, and so respect partial sends. The only
|
|
|
|
* problem is when a stream wsi wants to send an, eg,
|
|
|
|
* reply headers frame in response to the parsing
|
|
|
|
* we will do now... the *stream wsi* must stall in a
|
|
|
|
* different state until it is able to do so from a
|
|
|
|
* priority on the WRITABLE callback, same way that
|
|
|
|
* file transfers operate.
|
|
|
|
*/
|
|
|
|
|
2017-11-25 10:10:33 +08:00
|
|
|
if (lws_h2_parser(wsi, buf, len, &body_chunk_len)) {
|
|
|
|
lwsl_debug("%s: http2_parser bailed\n", __func__);
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
2014-10-08 12:00:53 +08:00
|
|
|
/* account for what we're using in rxflow buffer */
|
2017-10-13 10:33:02 +08:00
|
|
|
if (wsi->rxflow_buffer) {
|
2017-11-25 10:10:33 +08:00
|
|
|
wsi->rxflow_pos += (int)body_chunk_len;
|
2017-10-13 10:33:02 +08:00
|
|
|
assert(wsi->rxflow_pos <= wsi->rxflow_len);
|
|
|
|
}
|
|
|
|
|
2017-11-25 10:10:33 +08:00
|
|
|
buf += body_chunk_len;
|
|
|
|
len -= body_chunk_len;
|
2014-10-08 12:00:53 +08:00
|
|
|
}
|
2018-02-03 13:48:18 +08:00
|
|
|
// lwsl_debug("%s: used up block\n", __func__);
|
2014-10-08 12:00:53 +08:00
|
|
|
break;
|
2014-10-08 12:15:15 +08:00
|
|
|
#endif
|
ah owns rxbuf
This is intended to solve a longstanding problem with the
relationship between http/1.1 keep-alive and the service
loop.
Ah now contain an rx buffer which is used during header
processing, and the ah may not be detached from the wsi
until the rx buffer is exhausted.
Having the rx buffer in the ah means we can delay using the
rx until a later service loop.
Ah which have pending rx force POLLIN service on the wsi
they are attached to automatically, so we can interleave
general service / connections with draining each ah rx
buffer.
The possible http/1.1 situations and their dispositions are:
1) exactly one set of http headers come. After processing,
the ah is detached since no pending rx left. If more
headers come later, a fresh ah is aqcuired when available
and the rx flow control blocks the read until then.
2) more that one whole set of headers come and we remain in
http mode (no upgrade). The ah is left attached and
returns to the service loop after the first set of headers.
We will get forced service due to the ah having pending
content (respecting flowcontrol) and process the pending
rx in the ah. If we use it all up, we will detach the
ah.
3) one set of http headers come with ws traffic appended.
We service the headers, do the upgrade, and keep the ah
until the remaining ws content is used. When we
exhausted the ws traffix in the ah rx buffer, we
detach the ah.
Since there can be any amount of http/1.1 pipelining on a
connection, and each may be expensive to service, it's now
enforced there is a return to the service loop after each
header set is serviced on a connection.
When I added the forced service for ah with pending buffering,
I added support for it to the windows plat code. However this
is untested.
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-02-15 12:37:04 +08:00
|
|
|
|
2017-06-27 10:07:34 +08:00
|
|
|
case LWSS_HTTP_ISSUING_FILE:
|
|
|
|
return 0;
|
|
|
|
|
2016-04-18 17:26:14 +08:00
|
|
|
case LWSS_CLIENT_HTTP_ESTABLISHED:
|
|
|
|
break;
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP:
|
2014-08-06 08:58:23 -04:00
|
|
|
wsi->hdr_parsing_completed = 0;
|
2017-09-23 12:55:21 +08:00
|
|
|
|
2014-08-06 08:58:23 -04:00
|
|
|
/* fallthru */
|
2017-06-27 10:07:34 +08:00
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP_HEADERS:
|
2017-11-16 11:26:00 +08:00
|
|
|
if (!wsi->ah) {
|
2016-05-13 10:27:48 +08:00
|
|
|
lwsl_err("%s: LWSS_HTTP_HEADERS: NULL ah\n", __func__);
|
|
|
|
assert(0);
|
|
|
|
}
|
2013-01-10 19:50:35 +08:00
|
|
|
lwsl_parser("issuing %d bytes to parser\n", (int)len);
|
2011-01-22 12:51:57 +00:00
|
|
|
|
2017-06-09 20:20:42 +08:00
|
|
|
if (lws_handshake_client(wsi, &buf, (size_t)len))
|
2014-04-03 09:03:37 +08:00
|
|
|
goto bail;
|
2013-03-23 09:53:17 +08:00
|
|
|
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
last_char = buf;
|
2017-06-09 20:20:42 +08:00
|
|
|
if (lws_handshake_server(wsi, &buf, (size_t)len))
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
/* Handshake indicates this session is done. */
|
|
|
|
goto bail;
|
|
|
|
|
2017-03-07 16:06:05 +08:00
|
|
|
/* we might have transitioned to RAW */
|
|
|
|
if (wsi->mode == LWSCM_RAW)
|
|
|
|
/* we gave the read buffer to RAW handler already */
|
|
|
|
goto read_ok;
|
|
|
|
|
2015-12-28 14:24:49 +08:00
|
|
|
/*
|
|
|
|
* It's possible that we've exhausted our data already, or
|
|
|
|
* rx flow control has stopped us dealing with this early,
|
|
|
|
* but lws_handshake_server doesn't update len for us.
|
2015-12-17 17:03:59 +08:00
|
|
|
* Figure out how much was read, so that we can proceed
|
|
|
|
* appropriately:
|
|
|
|
*/
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
len -= (buf - last_char);
|
2018-02-03 13:48:18 +08:00
|
|
|
// lwsl_debug("%s: thinks we have used %ld\n", __func__, (long)len);
|
2014-07-19 07:00:52 +08:00
|
|
|
|
|
|
|
if (!wsi->hdr_parsing_completed)
|
|
|
|
/* More header content on the way */
|
|
|
|
goto read_ok;
|
|
|
|
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
switch (wsi->state) {
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP:
|
|
|
|
case LWSS_HTTP_HEADERS:
|
2016-02-24 20:58:19 +08:00
|
|
|
goto read_ok;
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP_ISSUING_FILE:
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
goto read_ok;
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP_BODY:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->http.rx_content_remain =
|
|
|
|
wsi->http.rx_content_length;
|
|
|
|
if (wsi->http.rx_content_remain)
|
2015-12-06 06:39:51 +08:00
|
|
|
goto http_postbody;
|
|
|
|
|
|
|
|
/* there is no POST content */
|
|
|
|
goto postbody_completion;
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP_BODY:
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
http_postbody:
|
2017-10-13 10:33:02 +08:00
|
|
|
//lwsl_notice("http post body\n");
|
2017-12-01 11:09:32 +08:00
|
|
|
while (len && wsi->http.rx_content_remain) {
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
/* Copy as much as possible, up to the limit of:
|
|
|
|
* what we have in the read buffer (len)
|
|
|
|
* remaining portion of the POST body (content_remain)
|
|
|
|
*/
|
2017-12-01 11:09:32 +08:00
|
|
|
body_chunk_len = min(wsi->http.rx_content_remain, len);
|
|
|
|
wsi->http.rx_content_remain -= body_chunk_len;
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
len -= body_chunk_len;
|
2016-02-21 21:25:48 +08:00
|
|
|
#ifdef LWS_WITH_CGI
|
|
|
|
if (wsi->cgi) {
|
|
|
|
struct lws_cgi_args args;
|
|
|
|
|
|
|
|
args.ch = LWS_STDIN;
|
|
|
|
args.stdwsi = &wsi->cgi->stdwsi[0];
|
|
|
|
args.data = buf;
|
|
|
|
args.len = body_chunk_len;
|
|
|
|
|
|
|
|
/* returns how much used */
|
|
|
|
n = user_callback_handle_rxflow(
|
|
|
|
wsi->protocol->callback,
|
|
|
|
wsi, LWS_CALLBACK_CGI_STDIN_DATA,
|
|
|
|
wsi->user_space,
|
|
|
|
(void *)&args, 0);
|
2016-03-20 11:55:25 +08:00
|
|
|
if ((int)n < 0)
|
2016-02-21 21:25:48 +08:00
|
|
|
goto bail;
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
n = wsi->protocol->callback(wsi,
|
|
|
|
LWS_CALLBACK_HTTP_BODY, wsi->user_space,
|
2017-06-09 20:20:42 +08:00
|
|
|
buf, (size_t)body_chunk_len);
|
2016-02-21 21:25:48 +08:00
|
|
|
if (n)
|
|
|
|
goto bail;
|
2017-06-09 20:20:42 +08:00
|
|
|
n = (size_t)body_chunk_len;
|
2016-02-21 21:25:48 +08:00
|
|
|
#ifdef LWS_WITH_CGI
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
buf += n;
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->http.rx_content_remain) {
|
2015-12-06 06:39:51 +08:00
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
|
2016-02-15 20:36:02 +08:00
|
|
|
wsi->context->timeout_secs);
|
2015-12-06 06:39:51 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* he sent all the content in time */
|
|
|
|
postbody_completion:
|
2016-08-23 14:20:11 +08:00
|
|
|
#ifdef LWS_WITH_CGI
|
2017-09-23 12:55:21 +08:00
|
|
|
/*
|
|
|
|
* If we're running a cgi, we can't let him off the
|
|
|
|
* hook just because he sent his POST data
|
|
|
|
*/
|
2016-08-23 14:20:11 +08:00
|
|
|
if (wsi->cgi)
|
2017-09-23 12:55:21 +08:00
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI,
|
|
|
|
wsi->context->timeout_secs);
|
2016-08-23 14:20:11 +08:00
|
|
|
else
|
|
|
|
#endif
|
2015-12-06 06:39:51 +08:00
|
|
|
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
2016-02-21 21:25:48 +08:00
|
|
|
#ifdef LWS_WITH_CGI
|
|
|
|
if (!wsi->cgi)
|
|
|
|
#endif
|
|
|
|
{
|
2017-10-28 07:42:44 +08:00
|
|
|
lwsl_notice("HTTP_BODY_COMPLETION\n");
|
2016-02-21 21:25:48 +08:00
|
|
|
n = wsi->protocol->callback(wsi,
|
|
|
|
LWS_CALLBACK_HTTP_BODY_COMPLETION,
|
|
|
|
wsi->user_space, NULL, 0);
|
|
|
|
if (n)
|
|
|
|
goto bail;
|
2017-10-13 10:33:02 +08:00
|
|
|
|
|
|
|
if (wsi->http2_substream)
|
|
|
|
wsi->state = LWSS_HTTP2_ESTABLISHED;
|
2016-02-21 21:25:48 +08:00
|
|
|
}
|
2015-12-06 06:39:51 +08:00
|
|
|
|
2016-05-09 09:37:44 +08:00
|
|
|
break;
|
2014-04-03 09:03:37 +08:00
|
|
|
}
|
2010-11-08 20:20:42 +00:00
|
|
|
break;
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_ESTABLISHED:
|
|
|
|
case LWSS_AWAITING_CLOSE_ACK:
|
2017-07-17 10:11:17 +08:00
|
|
|
case LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION:
|
2016-01-26 20:56:56 +08:00
|
|
|
case LWSS_SHUTDOWN:
|
2017-06-09 20:20:42 +08:00
|
|
|
if (lws_handshake_client(wsi, &buf, (size_t)len))
|
2014-04-10 14:08:10 +08:00
|
|
|
goto bail;
|
2011-02-09 07:16:34 +00:00
|
|
|
switch (wsi->mode) {
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSCM_WS_SERVING:
|
2017-11-14 07:35:05 +08:00
|
|
|
case LWSCM_HTTP2_WS_SERVING:
|
2011-01-22 12:51:57 +00:00
|
|
|
|
2017-10-28 07:42:44 +08:00
|
|
|
if (lws_interpret_incoming_packet(wsi, &buf,
|
|
|
|
(size_t)len) < 0) {
|
|
|
|
lwsl_info("interpret_incoming_packet bailed\n");
|
2014-04-10 14:08:10 +08:00
|
|
|
goto bail;
|
|
|
|
}
|
2011-02-09 07:16:34 +00:00
|
|
|
break;
|
2011-01-22 12:51:57 +00:00
|
|
|
}
|
2010-11-08 20:20:42 +00:00
|
|
|
break;
|
2017-12-07 18:48:21 +08:00
|
|
|
|
|
|
|
case LWSS_HTTP_DEFERRING_ACTION:
|
|
|
|
lwsl_debug("%s: LWSS_HTTP_DEFERRING_ACTION\n", __func__);
|
|
|
|
break;
|
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
default:
|
2016-04-18 17:26:14 +08:00
|
|
|
lwsl_err("%s: Unhandled state %d\n", __func__, wsi->state);
|
2017-11-24 10:54:59 +08:00
|
|
|
goto bail;
|
2010-11-08 20:20:42 +00:00
|
|
|
}
|
2010-11-13 10:03:47 +00:00
|
|
|
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
read_ok:
|
2015-12-06 06:39:51 +08:00
|
|
|
/* Nothing more to do for now */
|
2018-02-03 13:48:18 +08:00
|
|
|
// lwsl_info("%s: %p: read_ok, used %ld (len %d, state %d)\n", __func__,
|
|
|
|
// wsi, (long)(buf - oldbuf), (int)len, wsi->state);
|
HTTP Version, Keep-alive support, No-copy POST
This is a squashed commit from https://github.com/andrew-canaday/libwebsockets,
dev/http_keepalive branch (strategies changed a few times, so the commit
history is clutteread). This branch is submitted for clarity, but the other
can be used as a reference or alternative.
* added **enum http_version** to track HTTP/1.0 vs HTTP/1.1 requests
* added **enum http_connection_type** to track keep-alive vs close
* replaced content_length_seen and body_index with **content_remain**
* removed **post_buffer** (see handshake.c modifications)
* removed post_buffer free
* switch state to WSI_TOKEN_SKIPPING after URI is complete to store version
* delete *spill* label (unused)
* add vars to track HTTP version and connection type
* HTTP version defaults to 1.0
* connection type defaults to 'close' for 1.0, keep-alive for 1.1
* additional checks in **cleanup:** label:
* if HTTP version string is present and valid, set enum val appropriately
* override connection default with the "Connection:" header, if present
* set state to WSI_STATE_HTTP_BODY if content_length > 0
* return 0 on HTTP requests, unless LWS_CALLBACK_HTTP indicates otherwise
* add vars to track remaining content_length and body chunk size
* re-arrange switch case order to facilitate creation of jump-table
* added new labels:
* **read_ok**: normal location reach on break from switch; just return 0
* **http_complete**: check for keep-alive + init state, mode, hdr table
* **http_new**: jump location for keep-alive when http_complete sees len>0
* after libwebsocket_parse, jump to one of those labels based on state
* POST body handling:
* don't bother iterating over input byte-by-byte or using memcpy
* just pass the relevant portion of the context->service_buffer to callback
2014-07-13 01:07:36 -04:00
|
|
|
|
2017-10-25 08:00:23 +08:00
|
|
|
return lws_ptr_diff(buf, oldbuf);
|
2010-11-13 10:03:47 +00:00
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
bail:
|
2017-12-07 13:03:06 +08:00
|
|
|
/*
|
|
|
|
* h2 / h2-ws calls us recursively in lws_read()->lws_h2_parser()->
|
|
|
|
* lws_read() pattern. Make sure that only the outer lws_read() does
|
|
|
|
* the wsi close.
|
|
|
|
*/
|
|
|
|
if (!wsi->outer_will_close)
|
2018-02-03 13:48:18 +08:00
|
|
|
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "lws_read bail");
|
2011-01-23 16:50:33 +00:00
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|