mirror of
https://github.com/gabime/spdlog.git
synced 2026-10-28 09:45:28 +08:00
Fix refused Windows TCP connections with a timeout (#3683)
This commit is contained in:
1 parent
bfa795e5aa
commit
9af9f48d3d
2 files changed
+56
-2
No files matched your search
@@ -97,12 +97,13 @@ public:
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
// Wait until socket is writable or timeout expires
|
||||
// Wait until the connection succeeds, fails, or times out.
|
||||
fd_set wfds;
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(sockfd, &wfds);
|
||||
fd_set efds = wfds;
|
||||
|
||||
rv = ::select(0, nullptr, &wfds, nullptr, const_cast<timeval *>(&tv));
|
||||
rv = ::select(0, nullptr, &wfds, &efds, const_cast<timeval *>(&tv));
|
||||
|
||||
// Restore blocking mode regardless of select result
|
||||
mode = 0UL;
|
||||
|
||||
@@ -63,4 +63,57 @@ TEST_CASE("tcp_client timeout supports high file descriptors", "[tcp_sink]") {
|
||||
REQUIRE(client.connect_socket_with_timeout(
|
||||
high_fd.fd, reinterpret_cast<sockaddr *>(&addr), addr_len, 1000) == 0);
|
||||
}
|
||||
#else
|
||||
#include <spdlog/details/tcp_client-windows.h>
|
||||
|
||||
struct socket_guard {
|
||||
explicit socket_guard(SOCKET value)
|
||||
: fd(value) {}
|
||||
~socket_guard() {
|
||||
if (fd != INVALID_SOCKET) ::closesocket(fd);
|
||||
}
|
||||
SOCKET fd;
|
||||
};
|
||||
|
||||
TEST_CASE("tcp_client timeout reports refused Windows connections", "[tcp_sink]") {
|
||||
spdlog::details::tcp_client client;
|
||||
socket_guard bound(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
REQUIRE(bound.fd != INVALID_SOCKET);
|
||||
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
REQUIRE(::bind(bound.fd, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) == 0);
|
||||
int addr_len = sizeof(addr);
|
||||
REQUIRE(::getsockname(bound.fd, reinterpret_cast<sockaddr *>(&addr), &addr_len) == 0);
|
||||
|
||||
socket_guard outbound(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
REQUIRE(outbound.fd != INVALID_SOCKET);
|
||||
timeval timeout{3, 0};
|
||||
auto result = client.connect_socket_with_timeout(
|
||||
outbound.fd, reinterpret_cast<sockaddr *>(&addr), addr_len, timeout);
|
||||
auto error = ::WSAGetLastError();
|
||||
REQUIRE(result == SOCKET_ERROR);
|
||||
REQUIRE(error == WSAECONNREFUSED);
|
||||
}
|
||||
|
||||
TEST_CASE("tcp_client timeout connects to Windows listeners", "[tcp_sink]") {
|
||||
spdlog::details::tcp_client client;
|
||||
socket_guard listener(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
REQUIRE(listener.fd != INVALID_SOCKET);
|
||||
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
REQUIRE(::bind(listener.fd, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) == 0);
|
||||
REQUIRE(::listen(listener.fd, 1) == 0);
|
||||
int addr_len = sizeof(addr);
|
||||
REQUIRE(::getsockname(listener.fd, reinterpret_cast<sockaddr *>(&addr), &addr_len) == 0);
|
||||
|
||||
socket_guard outbound(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
REQUIRE(outbound.fd != INVALID_SOCKET);
|
||||
timeval timeout{3, 0};
|
||||
REQUIRE(client.connect_socket_with_timeout(outbound.fd, reinterpret_cast<sockaddr *>(&addr),
|
||||
addr_len, timeout) == 0);
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user