@@ -799,6 +799,7 @@ enum class Error {
799799 SSLServerVerification,
800800 UnsupportedMultipartBoundaryChars,
801801 Compression,
802+ ConnectionTimeout,
802803};
803804
804805std::string to_string (const Error error);
@@ -1594,6 +1595,7 @@ inline std::string to_string(const Error error) {
15941595 case Error::UnsupportedMultipartBoundaryChars:
15951596 return " UnsupportedMultipartBoundaryChars" ;
15961597 case Error::Compression: return " Compression" ;
1598+ case Error::ConnectionTimeout: return " ConnectionTimeout" ;
15971599 case Error::Unknown: return " Unknown" ;
15981600 default : break ;
15991601 }
@@ -2313,7 +2315,7 @@ inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) {
23132315#endif
23142316}
23152317
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) {
23172319#ifdef CPPHTTPLIB_USE_POLL
23182320 struct pollfd pfd_read;
23192321 pfd_read.fd = sock;
@@ -2323,17 +2325,23 @@ inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) {
23232325
23242326 auto poll_res = handle_EINTR ([&]() { return poll (&pfd_read, 1 , timeout); });
23252327
2328+ if (poll_res == 0 ) {
2329+ return Error::ConnectionTimeout;
2330+ }
2331+
23262332 if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) {
23272333 int error = 0 ;
23282334 socklen_t len = sizeof (error);
23292335 auto res = getsockopt (sock, SOL_SOCKET, SO_ERROR,
23302336 reinterpret_cast <char *>(&error), &len);
2331- return res >= 0 && !error;
2337+ auto successful = res >= 0 && !error;
2338+ return successful ? Error::Success : Error::Connection;
23322339 }
2333- return false ;
2340+
2341+ return Error::Connection;
23342342#else
23352343#ifndef _WIN32
2336- if (sock >= FD_SETSIZE) { return false ; }
2344+ if (sock >= FD_SETSIZE) { return Error::Connection ; }
23372345#endif
23382346
23392347 fd_set fdsr;
@@ -2351,14 +2359,19 @@ inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) {
23512359 return select (static_cast <int >(sock + 1 ), &fdsr, &fdsw, &fdse, &tv);
23522360 });
23532361
2362+ if (ret == 0 ) {
2363+ return Error::ConnectionTimeout;
2364+ }
2365+
23542366 if (ret > 0 && (FD_ISSET (sock, &fdsr) || FD_ISSET (sock, &fdsw))) {
23552367 int error = 0 ;
23562368 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;
23602373 }
2361- return false ;
2374+ return Error::Connection ;
23622375#endif
23632376}
23642377
@@ -2684,12 +2697,15 @@ inline socket_t create_client_socket(
26842697 ::connect (sock2, ai.ai_addr, static_cast <socklen_t >(ai.ai_addrlen));
26852698
26862699 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 ()) {
26902701 error = Error::Connection;
26912702 return false ;
26922703 }
2704+ error = wait_until_socket_is_ready (sock2, connection_timeout_sec,
2705+ connection_timeout_usec);
2706+ if (error != Error::Success) {
2707+ return false ;
2708+ }
26932709 }
26942710
26952711 set_nonblocking (sock2, false );
0 commit comments