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
|
|
|
*
|
2015-12-06 08:00:03 +08:00
|
|
|
* Copyright (C) 2010-2015 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
|
2015-12-16 18:19:08 +08:00
|
|
|
lws_read(struct lws *wsi, unsigned char *buf, size_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;
|
2015-12-06 08:00:03 +08:00
|
|
|
int body_chunk_len;
|
|
|
|
size_t n;
|
2010-11-13 10:03:47 +00:00
|
|
|
|
2016-04-10 09:33:54 +08:00
|
|
|
lwsl_debug("%s: incoming len %d state %d\n", __func__, (int)len, wsi->state);
|
2016-01-11 11:34:01 +08:00
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
switch (wsi->state) {
|
2014-10-08 12:15:15 +08:00
|
|
|
#ifdef LWS_USE_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:
|
2014-10-08 12:00:53 +08:00
|
|
|
n = 0;
|
|
|
|
while (n < len) {
|
|
|
|
/*
|
|
|
|
* we were accepting input but now we stopped doing so
|
|
|
|
*/
|
|
|
|
if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
|
|
|
|
lws_rxflow_cache(wsi, buf, n, len);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* account for what we're using in rxflow buffer */
|
|
|
|
if (wsi->rxflow_buffer)
|
|
|
|
wsi->rxflow_pos++;
|
2016-04-10 09:33:54 +08:00
|
|
|
if (lws_http2_parser(wsi, buf[n++])) {
|
|
|
|
lwsl_debug("%s: http2_parser bailed\n", __func__);
|
2014-10-08 12:00:53 +08:00
|
|
|
goto bail;
|
2016-04-10 09:33:54 +08:00
|
|
|
}
|
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
|
|
|
|
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;
|
|
|
|
/* fallthru */
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP_ISSUING_FILE:
|
|
|
|
wsi->state = LWSS_HTTP_HEADERS;
|
2013-01-21 11:04:23 +08:00
|
|
|
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
|
|
|
wsi->u.hdr.lextable_pos = 0;
|
2010-11-08 20:20:42 +00:00
|
|
|
/* fallthru */
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSS_HTTP_HEADERS:
|
2016-05-13 10:27:48 +08:00
|
|
|
if (!wsi->u.hdr.ah) {
|
|
|
|
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
|
|
|
|
2014-04-03 09:03:37 +08:00
|
|
|
if (lws_handshake_client(wsi, &buf, len))
|
|
|
|
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;
|
2015-12-16 18:19:08 +08:00
|
|
|
if (lws_handshake_server(wsi, &buf, 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);
|
2017-02-05 22:07:34 +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:
|
2015-12-06 06:39:51 +08:00
|
|
|
wsi->u.http.content_remain =
|
|
|
|
wsi->u.http.content_length;
|
|
|
|
if (wsi->u.http.content_remain)
|
|
|
|
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:
|
|
|
|
while (len && wsi->u.http.content_remain) {
|
|
|
|
/* 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)
|
|
|
|
*/
|
|
|
|
body_chunk_len = min(wsi->u.http.content_remain,len);
|
|
|
|
wsi->u.http.content_remain -= body_chunk_len;
|
|
|
|
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,
|
|
|
|
buf, body_chunk_len);
|
|
|
|
if (n)
|
|
|
|
goto bail;
|
|
|
|
n = body_chunk_len;
|
|
|
|
#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
|
|
|
|
2015-12-06 06:39:51 +08:00
|
|
|
if (wsi->u.http.content_remain) {
|
|
|
|
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
|
|
|
|
/* if we're running a cgi, we can't let him off the hook just because he sent his POST data */
|
|
|
|
if (wsi->cgi)
|
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, wsi->context->timeout_secs);
|
|
|
|
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
|
|
|
|
{
|
|
|
|
n = wsi->protocol->callback(wsi,
|
|
|
|
LWS_CALLBACK_HTTP_BODY_COMPLETION,
|
|
|
|
wsi->user_space, NULL, 0);
|
|
|
|
if (n)
|
|
|
|
goto bail;
|
|
|
|
}
|
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:
|
2016-01-26 20:56:56 +08:00
|
|
|
case LWSS_SHUTDOWN:
|
2014-04-10 14:08:10 +08:00
|
|
|
if (lws_handshake_client(wsi, &buf, len))
|
|
|
|
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:
|
2011-01-22 12:51:57 +00:00
|
|
|
|
2016-01-11 11:34:01 +08:00
|
|
|
if (lws_interpret_incoming_packet(wsi, &buf, len) < 0) {
|
2014-04-10 14:08:10 +08:00
|
|
|
lwsl_info("interpret_incoming_packet has bailed\n");
|
|
|
|
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;
|
|
|
|
default:
|
2016-04-18 17:26:14 +08:00
|
|
|
lwsl_err("%s: Unhandled state %d\n", __func__, wsi->state);
|
2010-11-08 20:20:42 +00:00
|
|
|
break;
|
|
|
|
}
|
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 */
|
2017-02-18 17:26:40 +08:00
|
|
|
lwsl_info("%s: read_ok, used %ld\n", __func__, (long)(buf - oldbuf));
|
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
|
|
|
|
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
|
|
|
return buf - oldbuf;
|
2010-11-13 10:03:47 +00:00
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
bail:
|
2016-07-23 14:18:25 +08:00
|
|
|
//lwsl_notice("closing connection at lws_read bail:\n");
|
2015-12-15 21:15:58 +08:00
|
|
|
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
2011-01-23 16:50:33 +00:00
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|