From 3792ce0da73ca24f501d433276c6f73428ae3f61 Mon Sep 17 00:00:00 2001 From: yhirose Date: Sun, 22 Mar 2026 22:31:59 -0400 Subject: [PATCH] Add socket configuration options and corresponding test case for WebSocketClient. Fix #2401 --- httplib.h | 39 +++++++++++++++++++++++++++++++++++++-- test/test.cc | 23 +++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/httplib.h b/httplib.h index ead218aa..86987052 100644 --- a/httplib.h +++ b/httplib.h @@ -3808,6 +3808,12 @@ public: void set_read_timeout(time_t sec, time_t usec = 0); void set_write_timeout(time_t sec, time_t usec = 0); void set_websocket_ping_interval(time_t sec); + void set_tcp_nodelay(bool on); + void set_address_family(int family); + void set_ipv6_v6only(bool on); + void set_socket_options(SocketOptions socket_options); + void set_connection_timeout(time_t sec, time_t usec = 0); + void set_interface(const std::string &intf); #ifdef CPPHTTPLIB_SSL_ENABLED void set_ca_cert_path(const std::string &path); @@ -3833,6 +3839,13 @@ private: time_t write_timeout_usec_ = CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND; time_t websocket_ping_interval_sec_ = CPPHTTPLIB_WEBSOCKET_PING_INTERVAL_SECOND; + int address_family_ = AF_UNSPEC; + bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY; + bool ipv6_v6only_ = CPPHTTPLIB_IPV6_V6ONLY; + SocketOptions socket_options_ = nullptr; + time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND; + time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND; + std::string interface_; #ifdef CPPHTTPLIB_SSL_ENABLED bool is_ssl_ = false; @@ -20195,9 +20208,10 @@ inline bool WebSocketClient::connect() { Error error; sock_ = detail::create_client_socket( - host_, std::string(), port_, AF_UNSPEC, false, false, nullptr, 5, 0, + host_, std::string(), port_, address_family_, tcp_nodelay_, ipv6_v6only_, + socket_options_, connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, std::string(), error); + write_timeout_usec_, interface_, error); if (sock_ == INVALID_SOCKET) { return false; } @@ -20263,6 +20277,27 @@ inline void WebSocketClient::set_websocket_ping_interval(time_t sec) { websocket_ping_interval_sec_ = sec; } +inline void WebSocketClient::set_tcp_nodelay(bool on) { tcp_nodelay_ = on; } + +inline void WebSocketClient::set_address_family(int family) { + address_family_ = family; +} + +inline void WebSocketClient::set_ipv6_v6only(bool on) { ipv6_v6only_ = on; } + +inline void WebSocketClient::set_socket_options(SocketOptions socket_options) { + socket_options_ = std::move(socket_options); +} + +inline void WebSocketClient::set_connection_timeout(time_t sec, time_t usec) { + connection_timeout_sec_ = sec; + connection_timeout_usec_ = usec; +} + +inline void WebSocketClient::set_interface(const std::string &intf) { + interface_ = intf; +} + #ifdef CPPHTTPLIB_SSL_ENABLED inline void WebSocketClient::set_ca_cert_path(const std::string &path) { diff --git a/test/test.cc b/test/test.cc index 2c334fbd..b7f54af7 100644 --- a/test/test.cc +++ b/test/test.cc @@ -17088,6 +17088,29 @@ TEST_F(WebSocketIntegrationTest, SubProtocolNotRequested) { client.close(); } +TEST_F(WebSocketIntegrationTest, SocketSettings) { + ws::WebSocketClient client("ws://localhost:" + std::to_string(port_) + + "/ws-echo"); + client.set_tcp_nodelay(true); + client.set_address_family(AF_INET); + client.set_connection_timeout(3, 0); + + bool socket_options_called = false; + client.set_socket_options([&](socket_t) { socket_options_called = true; }); + + ASSERT_TRUE(client.connect()); + ASSERT_TRUE(client.is_open()); + EXPECT_TRUE(socket_options_called); + + ASSERT_TRUE(client.send("hello")); + std::string msg; + auto result = client.read(msg); + EXPECT_EQ(result, ws::ReadResult::Text); + EXPECT_EQ(msg, "hello"); + + client.close(); +} + TEST(WebSocketPreRoutingTest, RejectWithoutAuth) { Server svr;