From 21c529229c11f5a37042eaee3e26bbcdf04f7986 Mon Sep 17 00:00:00 2001 From: yhirose Date: Fri, 16 Apr 2021 22:03:57 -0400 Subject: [PATCH] Fixed timeout issues --- httplib.h | 54 ++++++++++++++++++++++++++++++++++++++++++---------- test/test.cc | 5 ++++- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/httplib.h b/httplib.h index e5eba09..60acbb9 100644 --- a/httplib.h +++ b/httplib.h @@ -2091,8 +2091,9 @@ socket_t create_socket(const char *host, int port, int address_family, for (auto rp = result; rp; rp = rp->ai_next) { // Create a socket #ifdef _WIN32 - auto sock = WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol, - nullptr, 0, WSA_FLAG_NO_HANDLE_INHERIT); + auto sock = + WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol, nullptr, 0, + WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); /** * Since the WSA_FLAG_NO_HANDLE_INHERIT is only supported on Windows 7 SP1 * and above the socket creation fails on older Windows Systems. @@ -2214,11 +2215,12 @@ inline std::string if2ip(const std::string &ifn) { } #endif -inline socket_t create_client_socket(const char *host, int port, - int address_family, bool tcp_nodelay, - SocketOptions socket_options, - time_t timeout_sec, time_t timeout_usec, - const std::string &intf, Error &error) { +inline socket_t create_client_socket( + const char *host, int port, int address_family, bool tcp_nodelay, + SocketOptions socket_options, time_t connection_timeout_sec, + time_t connection_timeout_usec, time_t read_timeout_sec, + time_t read_timeout_usec, time_t write_timeout_sec, + time_t write_timeout_usec, const std::string &intf, Error &error) { auto sock = create_socket( host, port, address_family, 0, tcp_nodelay, std::move(socket_options), [&](socket_t sock, struct addrinfo &ai) -> bool { @@ -2240,7 +2242,8 @@ inline socket_t create_client_socket(const char *host, int port, if (ret < 0) { if (is_connection_error() || - !wait_until_socket_is_ready(sock, timeout_sec, timeout_usec)) { + !wait_until_socket_is_ready(sock, connection_timeout_sec, + connection_timeout_usec)) { close_socket(sock); error = Error::Connection; return false; @@ -2248,6 +2251,21 @@ inline socket_t create_client_socket(const char *host, int port, } set_nonblocking(sock, false); + + { + timeval tv; + tv.tv_sec = static_cast(read_timeout_sec); + tv.tv_usec = static_cast(read_timeout_usec); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); + } + { + timeval tv; + tv.tv_sec = static_cast(write_timeout_sec); + tv.tv_usec = + static_cast(write_timeout_usec); + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); + } + error = Error::Success; return true; }); @@ -4847,6 +4865,19 @@ inline bool Server::listen_internal() { break; } + { + timeval tv; + tv.tv_sec = static_cast(read_timeout_sec_); + tv.tv_usec = static_cast(read_timeout_usec_); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); + } + { + timeval tv; + tv.tv_sec = static_cast(write_timeout_sec_); + tv.tv_usec = static_cast(write_timeout_usec_); + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); + } + #if __cplusplus > 201703L task_queue->enqueue([=, this]() { process_and_close_socket(sock); }); #else @@ -5263,11 +5294,14 @@ inline socket_t ClientImpl::create_client_socket(Error &error) const { return detail::create_client_socket( proxy_host_.c_str(), proxy_port_, address_family_, tcp_nodelay_, socket_options_, connection_timeout_sec_, connection_timeout_usec_, - interface_, error); + read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, + write_timeout_usec_, interface_, error); } return detail::create_client_socket( host_.c_str(), port_, address_family_, tcp_nodelay_, socket_options_, - connection_timeout_sec_, connection_timeout_usec_, interface_, error); + connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, + read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_, + error); } inline bool ClientImpl::create_and_connect_socket(Socket &socket, diff --git a/test/test.cc b/test/test.cc index 08a0e12..91a905c 100644 --- a/test/test.cc +++ b/test/test.cc @@ -3145,7 +3145,10 @@ static bool send_request(time_t read_timeout_sec, const std::string &req, auto client_sock = detail::create_client_socket(HOST, PORT, AF_UNSPEC, false, nullptr, - /*timeout_sec=*/5, 0, std::string(), error); + /*connection_timeout_sec=*/5, 0, + /*read_timeout_sec=*/5, 0, + /*write_timeout_sec=*/5, 0, + std::string(), error); if (client_sock == INVALID_SOCKET) { return false; }