summaryrefslogtreecommitdiff
path: root/src/mod_wstunnel.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2022-03-24 04:21:11 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2022-03-25 08:43:42 -0400
commit5d1aa5d06f1dcae64481c142f7daaa0b08aee8d3 (patch)
tree3db59449f9dc69847f3cf29506d31e0135d00055 /src/mod_wstunnel.c
parent8fe9f1c053d828f666c0498d8b4281efabe6d3a6 (diff)
downloadlighttpd-git-5d1aa5d06f1dcae64481c142f7daaa0b08aee8d3.tar.gz
[multiple] WebSockets over HTTP/2 (fixes #3151)
Add support for WebSockets over HTTP/2 to lighttpd core and to mod_cgi w/ config: cgi.upgrade = "enable" mod_proxy w/ config: proxy.header += ("upgrade" => "enable") mod_wstunnel HTTP/2 CONNECT extension defined in RFC8441 is translated to HTTP/1.1 'Upgrade: websocket' requests to mod_cgi or mod_proxy, and is handled directly in mod_wstunnel. x-ref: WebSockets over HTTP/2 https://redmine.lighttpd.net/issues/3151 Bootstrapping WebSockets with HTTP/2 https://datatracker.ietf.org/doc/html/rfc8441
Diffstat (limited to 'src/mod_wstunnel.c')
-rw-r--r--src/mod_wstunnel.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/src/mod_wstunnel.c b/src/mod_wstunnel.c
index 6d17d4d4..df0715cf 100644
--- a/src/mod_wstunnel.c
+++ b/src/mod_wstunnel.c
@@ -349,14 +349,16 @@ static handler_t wstunnel_create_env(gw_handler_ctx *gwhctx) {
handler_ctx *hctx = (handler_ctx *)gwhctx;
request_st * const r = hctx->gw.r;
handler_t rc;
- if (0 == r->reqbody_length) {
+ if (0 == r->reqbody_length || r->http_version > HTTP_VERSION_1_1) {
http_response_upgrade_read_body_unknown(r);
chunkqueue_append_chunkqueue(&r->reqbody_queue, &r->read_queue);
}
rc = mod_wstunnel_handshake_create_response(hctx);
if (rc != HANDLER_GO_ON) return rc;
- r->http_status = 101; /* Switching Protocols */
+ r->http_status = (r->http_version > HTTP_VERSION_1_1)
+ ? 200 /* OK (response status for CONNECT) */
+ : 101; /* Switching Protocols */
r->resp_body_started = 1;
hctx->ping_ts = log_monotonic_secs;
@@ -553,11 +555,15 @@ static handler_t wstunnel_handler_setup (request_st * const r, plugin_data * con
static handler_t mod_wstunnel_check_extension(request_st * const r, void *p_d) {
plugin_data *p = p_d;
- const buffer *vb;
handler_t rc;
if (NULL != r->handler_module)
return HANDLER_GO_ON;
+ if (r->http_version > HTTP_VERSION_1_1) {
+ if (!r->h2_connect_ext)
+ return HANDLER_GO_ON;
+ }
+ else {
if (r->http_method != HTTP_METHOD_GET)
return HANDLER_GO_ON;
if (r->http_version != HTTP_VERSION_1_1)
@@ -567,6 +573,7 @@ static handler_t mod_wstunnel_check_extension(request_st * const r, void *p_d) {
* Connection: upgrade, keep-alive, ...
* Upgrade: WebSocket, ...
*/
+ const buffer *vb;
vb = http_header_request_get(r, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"));
if (NULL == vb
|| !http_header_str_contains_token(BUF_PTR_LEN(vb), CONST_STR_LEN("websocket")))
@@ -575,6 +582,7 @@ static handler_t mod_wstunnel_check_extension(request_st * const r, void *p_d) {
if (NULL == vb
|| !http_header_str_contains_token(BUF_PTR_LEN(vb), CONST_STR_LEN("upgrade")))
return HANDLER_GO_ON;
+ }
mod_wstunnel_patch_config(r, p);
if (NULL == p->conf.gw.exts) return HANDLER_GO_ON;
@@ -774,6 +782,7 @@ static int create_response_ietf_00(handler_ctx *hctx) {
static int create_response_rfc_6455(handler_ctx *hctx) {
request_st * const r = hctx->gw.r;
+ if (r->http_version == HTTP_VERSION_1_1) {
SHA_CTX sha;
unsigned char sha_digest[SHA_DIGEST_LENGTH];
@@ -804,6 +813,7 @@ static int create_response_rfc_6455(handler_ctx *hctx) {
http_header_response_set_ptr(r, HTTP_HEADER_OTHER,
CONST_STR_LEN("Sec-WebSocket-Accept"));
buffer_append_base64_encode(value, sha_digest, SHA_DIGEST_LENGTH, BASE64_STANDARD);
+ }
if (hctx->frame.type == MOD_WEBSOCKET_FRAME_TYPE_BIN)
http_header_response_set(r, HTTP_HEADER_OTHER,
@@ -834,7 +844,7 @@ handler_t mod_wstunnel_handshake_create_response(handler_ctx *hctx) {
#endif /* _MOD_WEBSOCKET_SPEC_RFC_6455_ */
#ifdef _MOD_WEBSOCKET_SPEC_IETF_00_
- if (hctx->hybivers == 0) {
+ if (hctx->hybivers == 0 && r->http_version == HTTP_VERSION_1_1) {
#ifdef _MOD_WEBSOCKET_SPEC_IETF_00_
/* 8 bytes should have been sent with request
* for draft-ietf-hybi-thewebsocketprotocol-00 */