From 3c17cb206fd257e03ce12f98f45998d10fc69097 Mon Sep 17 00:00:00 2001 From: Andrew Guz Date: Thu, 9 Jan 2025 10:39:47 +0300 Subject: [PATCH 1/4] Possibility to mirror Sec-WebSocket-Protocols --- include/crow/routing.h | 11 +++++++++-- include/crow/websocket.h | 8 +++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/crow/routing.h b/include/crow/routing.h index 26690a50a..de79a4df5 100644 --- a/include/crow/routing.h +++ b/include/crow/routing.h @@ -440,12 +440,12 @@ namespace crow // NOTE: Already documented in "crow/app.h" void handle_upgrade(const request& req, response&, SocketAdaptor&& adaptor) override { max_payload_ = max_payload_override_ ? max_payload_ : app_->websocket_max_payload(); - new crow::websocket::Connection(req, std::move(adaptor), app_, max_payload_, subprotocols_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_); + new crow::websocket::Connection(req, std::move(adaptor), app_, max_payload_, subprotocols_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_, mirror_protocols_); } #ifdef CROW_ENABLE_SSL void handle_upgrade(const request& req, response&, SSLAdaptor&& adaptor) override { - new crow::websocket::Connection(req, std::move(adaptor), app_, max_payload_, subprotocols_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_); + new crow::websocket::Connection(req, std::move(adaptor), app_, max_payload_, subprotocols_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_, mirror_protocols_); } #endif @@ -498,6 +498,12 @@ namespace crow // NOTE: Already documented in "crow/app.h" return *this; } + self_t& mirrorprotocols() + { + mirror_protocols_ = true; + return *this; + } + protected: App* app_; std::function open_handler_; @@ -505,6 +511,7 @@ namespace crow // NOTE: Already documented in "crow/app.h" std::function close_handler_; std::function error_handler_; std::function accept_handler_; + bool mirror_protocols_ = false; uint64_t max_payload_; bool max_payload_override_ = false; std::vector subprotocols_; diff --git a/include/crow/websocket.h b/include/crow/websocket.h index fa5e18546..a315226f6 100644 --- a/include/crow/websocket.h +++ b/include/crow/websocket.h @@ -116,7 +116,8 @@ namespace crow // NOTE: Already documented in "crow/app.h" std::function message_handler, std::function close_handler, std::function error_handler, - std::function accept_handler): + std::function accept_handler, + bool mirror_protocols): adaptor_(std::move(adaptor)), handler_(handler), max_payload_bytes_(max_payload), @@ -145,6 +146,11 @@ namespace crow // NOTE: Already documented in "crow/app.h" } } + if (mirror_protocols & !requested_subprotocols_header.empty()) + { + subprotocol_ = requested_subprotocols_header; + } + if (accept_handler_) { void* ud = nullptr; From 1760ed4380f684dd9237ff3f76153e63f99bef57 Mon Sep 17 00:00:00 2001 From: Andrew Guz Date: Thu, 9 Jan 2025 11:04:10 +0300 Subject: [PATCH 2/4] Unit test for possibility to mirror Sec-WebSocket-Protocols --- tests/unittest.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/unittest.cpp b/tests/unittest.cpp index 2d3945dd2..2ed0e0820 100644 --- a/tests/unittest.cpp +++ b/tests/unittest.cpp @@ -3200,6 +3200,57 @@ TEST_CASE("websocket_subprotocols") app.stop(); } +TEST_CASE("mirror_websocket_subprotocols") +{ + static std::string http_message = "GET /ws HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nupgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Protocol: protocol1, protocol2\r\nSec-WebSocket-Version: 13\r\nHost: localhost\r\n\r\n"; + + static websocket::connection* connection = nullptr; + static bool connected{false}; + + SimpleApp app; + + CROW_WEBSOCKET_ROUTE(app, "/ws") + .mirrorprotocols() + .onaccept([&](const crow::request& req, void**) { + CROW_LOG_INFO << "Accepted websocket with URL " << req.url; + return true; + }) + .onopen([&](websocket::connection& con) { + connected = true; + connection = &con; + CROW_LOG_INFO << "Connected websocket and subprotocol is " << con.get_subprotocol(); + }) + .onclose([&](websocket::connection&, const std::string&, uint16_t) { + CROW_LOG_INFO << "Closing websocket"; + }); + + app.validate(); + + auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async(); + app.wait_for_server_start(); + asio::io_context ic; + + asio::ip::tcp::socket c(ic); + c.connect(asio::ip::tcp::endpoint( + asio::ip::make_address(LOCALHOST_ADDRESS), 45451)); + + + char buf[2048]; + + //----------Handshake---------- + { + std::fill_n(buf, 2048, 0); + c.send(asio::buffer(http_message)); + + c.receive(asio::buffer(buf, 2048)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + CHECK(connected); + CHECK(connection->get_subprotocol() == "protocol1, protocol2"); + } + + app.stop(); +} + #ifdef CROW_ENABLE_COMPRESSION TEST_CASE("zlib_compression") { From 3da9c2c75199ad5401ab8680086a8224b3ce0a6e Mon Sep 17 00:00:00 2001 From: Andrew Guz Date: Thu, 9 Jan 2025 12:55:51 +0300 Subject: [PATCH 3/4] Review points --- tests/unittest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unittest.cpp b/tests/unittest.cpp index 2ed0e0820..ece43cd7f 100644 --- a/tests/unittest.cpp +++ b/tests/unittest.cpp @@ -3204,8 +3204,8 @@ TEST_CASE("mirror_websocket_subprotocols") { static std::string http_message = "GET /ws HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nupgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Protocol: protocol1, protocol2\r\nSec-WebSocket-Version: 13\r\nHost: localhost\r\n\r\n"; - static websocket::connection* connection = nullptr; - static bool connected{false}; + websocket::connection* connection = nullptr; + bool connected{false}; SimpleApp app; From b23953cb74067fd392c9e9aec49a9e40487a636e Mon Sep 17 00:00:00 2001 From: Andrew Guz Date: Fri, 10 Jan 2025 12:11:30 +0300 Subject: [PATCH 4/4] Review points --- include/crow/routing.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/crow/routing.h b/include/crow/routing.h index de79a4df5..1ee7b0f57 100644 --- a/include/crow/routing.h +++ b/include/crow/routing.h @@ -498,9 +498,9 @@ namespace crow // NOTE: Already documented in "crow/app.h" return *this; } - self_t& mirrorprotocols() + self_t& mirrorprotocols(bool mirror_protocols = true) { - mirror_protocols_ = true; + mirror_protocols_ = mirror_protocols; return *this; }