From 00c94beaf0d73457e15f55170ab088db337b7435 Mon Sep 17 00:00:00 2001 From: Dmitry Ilyin Date: Mon, 22 Jul 2024 21:47:53 +0300 Subject: [PATCH] ws: allow Upgrade in Connection header anywhere This will make it work for Firefox, which uses "Connection: keep-alive, Upgrade" Reimplemented our own evutil_ascii_strcasestr function (same as non-portable strcasestr) --- evutil.c | 19 +++++++++++++++++++ test/regress_ws.c | 15 +++++++++++---- util-internal.h | 6 ++++++ ws.c | 2 +- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/evutil.c b/evutil.c index ea3df613..72b87ce9 100644 --- a/evutil.c +++ b/evutil.c @@ -2625,6 +2625,25 @@ int evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n) return 0; } +const char* evutil_ascii_strcasestr(const char* s, const char *find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + c = EVUTIL_TOLOWER_(c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while ((char)EVUTIL_TOLOWER_(sc) != c); + } while (evutil_ascii_strncasecmp(s, find, len) != 0); + s--; + } + return s; +} + void evutil_rtrim_lws_(char *str) { diff --git a/test/regress_ws.c b/test/regress_ws.c index e9b62953..5dc29009 100644 --- a/test/regress_ws.c +++ b/test/regress_ws.c @@ -337,8 +337,8 @@ http_ws_readcb_bad(struct bufferevent *bev, void *arg) free(line); } -void -http_ws_test(void *arg) +static void +http_ws_test_with_connection(void *arg, const char* conn_value) { struct basic_test_data *data = arg; struct bufferevent *bev = NULL; @@ -377,10 +377,10 @@ http_ws_test(void *arg) evbuffer_add_printf(out, "GET /ws HTTP/1.1\r\n" "Host: somehost\r\n" - "Connection: Upgrade\r\n" + "Connection: %s\r\n" "Upgrade: websocket\r\n" "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n" - "\r\n"); + "\r\n", conn_value); test_ok = 0; event_base_dispatch(data->base); @@ -391,3 +391,10 @@ end: if (bev) bufferevent_free(bev); } + +void +http_ws_test(void *arg) +{ + http_ws_test_with_connection(arg, "Upgrade"); + http_ws_test_with_connection(arg, "keep-alive, Upgrade"); +} diff --git a/util-internal.h b/util-internal.h index f6f4856a..8cd08497 100644 --- a/util-internal.h +++ b/util-internal.h @@ -569,6 +569,12 @@ int evutil_v4addr_is_local_(const struct in_addr *in); EVENT2_EXPORT_SYMBOL int evutil_v6addr_is_local_(const struct in6_addr *in); +/** As strcasestr, but always searching substring in locale-independent + ASCII. That's useful if you're handling data in ASCII-based protocols. + */ +EVENT2_EXPORT_SYMBOL +const char* evutil_ascii_strcasestr(const char* s, const char *find); + #ifdef __cplusplus } #endif diff --git a/ws.c b/ws.c index e9cd9785..8764080e 100644 --- a/ws.c +++ b/ws.c @@ -386,7 +386,7 @@ evws_new_session( goto error; connection = evhttp_find_header(in_hdrs, "Connection"); - if (connection == NULL || evutil_ascii_strcasecmp(connection, "Upgrade")) + if (connection == NULL || evutil_ascii_strcasestr(connection, "Upgrade") == NULL) goto error; ws_key = evhttp_find_header(in_hdrs, "Sec-WebSocket-Key");