@@ -799,6 +799,7 @@ enum class Error {
799
799
SSLServerVerification,
800
800
UnsupportedMultipartBoundaryChars,
801
801
Compression,
802
+ ConnectionTimeout,
802
803
};
803
804
804
805
std::string to_string (const Error error);
@@ -1594,6 +1595,7 @@ inline std::string to_string(const Error error) {
1594
1595
case Error::UnsupportedMultipartBoundaryChars:
1595
1596
return " UnsupportedMultipartBoundaryChars" ;
1596
1597
case Error::Compression: return " Compression" ;
1598
+ case Error::ConnectionTimeout: return " ConnectionTimeout" ;
1597
1599
case Error::Unknown: return " Unknown" ;
1598
1600
default : break ;
1599
1601
}
@@ -2313,7 +2315,7 @@ inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) {
2313
2315
#endif
2314
2316
}
2315
2317
2316
- inline bool wait_until_socket_is_ready (socket_t sock, time_t sec, time_t usec) {
2318
+ inline Error wait_until_socket_is_ready (socket_t sock, time_t sec, time_t usec) {
2317
2319
#ifdef CPPHTTPLIB_USE_POLL
2318
2320
struct pollfd pfd_read;
2319
2321
pfd_read.fd = sock;
@@ -2323,17 +2325,23 @@ inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) {
2323
2325
2324
2326
auto poll_res = handle_EINTR ([&]() { return poll (&pfd_read, 1 , timeout); });
2325
2327
2328
+ if (poll_res == 0 ) {
2329
+ return Error::ConnectionTimeout;
2330
+ }
2331
+
2326
2332
if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) {
2327
2333
int error = 0 ;
2328
2334
socklen_t len = sizeof (error);
2329
2335
auto res = getsockopt (sock, SOL_SOCKET, SO_ERROR,
2330
2336
reinterpret_cast <char *>(&error), &len);
2331
- return res >= 0 && !error;
2337
+ auto successful = res >= 0 && !error;
2338
+ return successful ? Error::Success : Error::Connection;
2332
2339
}
2333
- return false ;
2340
+
2341
+ return Error::Connection;
2334
2342
#else
2335
2343
#ifndef _WIN32
2336
- if (sock >= FD_SETSIZE) { return false ; }
2344
+ if (sock >= FD_SETSIZE) { return Error::Connection ; }
2337
2345
#endif
2338
2346
2339
2347
fd_set fdsr;
@@ -2351,14 +2359,19 @@ inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) {
2351
2359
return select (static_cast <int >(sock + 1 ), &fdsr, &fdsw, &fdse, &tv);
2352
2360
});
2353
2361
2362
+ if (ret == 0 ) {
2363
+ return Error::ConnectionTimeout;
2364
+ }
2365
+
2354
2366
if (ret > 0 && (FD_ISSET (sock, &fdsr) || FD_ISSET (sock, &fdsw))) {
2355
2367
int error = 0 ;
2356
2368
socklen_t len = sizeof (error);
2357
- return getsockopt (sock, SOL_SOCKET, SO_ERROR,
2358
- reinterpret_cast <char *>(&error), &len) >= 0 &&
2359
- !error;
2369
+ auto res = getsockopt (sock, SOL_SOCKET, SO_ERROR,
2370
+ reinterpret_cast <char *>(&error), &len);
2371
+ auto successful = res >= 0 && !error;
2372
+ return successful ? Error::Success : Error::Connection;
2360
2373
}
2361
- return false ;
2374
+ return Error::Connection ;
2362
2375
#endif
2363
2376
}
2364
2377
@@ -2684,12 +2697,15 @@ inline socket_t create_client_socket(
2684
2697
::connect (sock2, ai.ai_addr, static_cast <socklen_t >(ai.ai_addrlen));
2685
2698
2686
2699
if (ret < 0 ) {
2687
- if (is_connection_error () ||
2688
- !wait_until_socket_is_ready (sock2, connection_timeout_sec,
2689
- connection_timeout_usec)) {
2700
+ if (is_connection_error ()) {
2690
2701
error = Error::Connection;
2691
2702
return false ;
2692
2703
}
2704
+ error = wait_until_socket_is_ready (sock2, connection_timeout_sec,
2705
+ connection_timeout_usec);
2706
+ if (error != Error::Success) {
2707
+ return false ;
2708
+ }
2693
2709
}
2694
2710
2695
2711
set_nonblocking (sock2, false );
0 commit comments