aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2020-10-14 04:17:55 +0200
committerPřemysl Eric Janouch <p@janouch.name>2020-10-14 09:44:46 +0200
commitad1aba9d2298f310448b1a6bfba0d382efb8a03e (patch)
tree56dbd65860e6c62773584af1dc256969c6ff994f
parent0107d09abc5fb6e4cfca5788d03632a590cecf74 (diff)
downloadjson-rpc-shell-ad1aba9d2298f310448b1a6bfba0d382efb8a03e.tar.gz
json-rpc-shell-ad1aba9d2298f310448b1a6bfba0d382efb8a03e.tar.xz
json-rpc-shell-ad1aba9d2298f310448b1a6bfba0d382efb8a03e.zip
WebSocket: fix upgrade processing
When http-parser sets the upgrade field, it checks for status code 101 and even resolves our TODO about checking the entire Connection header.
-rw-r--r--json-rpc-shell.c20
1 files changed, 6 insertions, 14 deletions
diff --git a/json-rpc-shell.c b/json-rpc-shell.c
index 8c2d64f..72e14a4 100644
--- a/json-rpc-shell.c
+++ b/json-rpc-shell.c
@@ -1538,7 +1538,7 @@ backend_ws_header_field_is_a_list (const char *name)
{
// This must contain all header fields we use for anything
static const char *concatenable[] =
- { SEC_WS_PROTOCOL, SEC_WS_EXTENSIONS, "Connection", "Upgrade" };
+ { SEC_WS_PROTOCOL, SEC_WS_EXTENSIONS, "Upgrade" };
for (size_t i = 0; i < N_ELEMENTS (concatenable); i++)
if (!strcasecmp_ascii (name, concatenable[i]))
@@ -1604,9 +1604,10 @@ backend_ws_on_headers_complete (http_parser *parser)
if (self->have_header_value)
backend_ws_on_header_read (self);
- // We strictly require a protocol upgrade
+ // We require a protocol upgrade. 1 is for "skip body", 2 is the same
+ // + "stop processing", return another number to indicate a problem here.
if (!parser->upgrade)
- return 2;
+ return 3;
return 0;
}
@@ -1618,20 +1619,10 @@ backend_ws_finish_handshake (struct ws_context *self, struct error **e)
FAIL ("incompatible HTTP version: %d.%d",
self->hp.http_major, self->hp.http_minor);
- if (self->hp.status_code != 101)
- // TODO: handle other codes?
- FAIL ("unexpected status code: %d", self->hp.status_code);
-
const char *upgrade = str_map_find (&self->headers, "Upgrade");
if (!upgrade || strcasecmp_ascii (upgrade, "websocket"))
FAIL ("cannot upgrade connection to WebSocket");
- const char *connection = str_map_find (&self->headers, "Connection");
- if (!connection || strcasecmp_ascii (connection, "Upgrade"))
- // XXX: maybe we shouldn't be so strict and only check for presence
- // of the "Upgrade" token in this list
- FAIL ("cannot upgrade connection to WebSocket");
-
const char *accept = str_map_find (&self->headers, SEC_WS_ACCEPT);
char *accept_expected = ws_encode_response_key (self->key);
bool accept_ok = accept && !strcmp (accept, accept_expected);
@@ -1691,7 +1682,8 @@ backend_ws_on_data (struct ws_context *self, const void *data, size_t len)
if (n_parsed != len || err != HPE_OK)
{
if (err == HPE_CB_headers_complete)
- print_error ("WS handshake failed: %s", "missing `Upgrade' field");
+ print_error ("WS handshake failed: %s (status code %d)",
+ "connection cannot be upgraded", self->hp.status_code);
else
print_error ("WS handshake failed: %s",
http_errno_description (err));