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.
This commit is contained in:
parent
0107d09abc
commit
ad1aba9d22
|
@ -1538,7 +1538,7 @@ backend_ws_header_field_is_a_list (const char *name)
|
||||||
{
|
{
|
||||||
// This must contain all header fields we use for anything
|
// This must contain all header fields we use for anything
|
||||||
static const char *concatenable[] =
|
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++)
|
for (size_t i = 0; i < N_ELEMENTS (concatenable); i++)
|
||||||
if (!strcasecmp_ascii (name, 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)
|
if (self->have_header_value)
|
||||||
backend_ws_on_header_read (self);
|
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)
|
if (!parser->upgrade)
|
||||||
return 2;
|
return 3;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1618,20 +1619,10 @@ backend_ws_finish_handshake (struct ws_context *self, struct error **e)
|
||||||
FAIL ("incompatible HTTP version: %d.%d",
|
FAIL ("incompatible HTTP version: %d.%d",
|
||||||
self->hp.http_major, self->hp.http_minor);
|
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");
|
const char *upgrade = str_map_find (&self->headers, "Upgrade");
|
||||||
if (!upgrade || strcasecmp_ascii (upgrade, "websocket"))
|
if (!upgrade || strcasecmp_ascii (upgrade, "websocket"))
|
||||||
FAIL ("cannot upgrade connection to 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);
|
const char *accept = str_map_find (&self->headers, SEC_WS_ACCEPT);
|
||||||
char *accept_expected = ws_encode_response_key (self->key);
|
char *accept_expected = ws_encode_response_key (self->key);
|
||||||
bool accept_ok = accept && !strcmp (accept, accept_expected);
|
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 (n_parsed != len || err != HPE_OK)
|
||||||
{
|
{
|
||||||
if (err == HPE_CB_headers_complete)
|
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
|
else
|
||||||
print_error ("WS handshake failed: %s",
|
print_error ("WS handshake failed: %s",
|
||||||
http_errno_description (err));
|
http_errno_description (err));
|
||||||
|
|
Loading…
Reference in New Issue