1818#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
1919#endif
2020
21+ #ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND
22+ #define CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND 10000
23+ #endif
24+
2125#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT
2226#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 100
2327#endif
@@ -3251,6 +3255,41 @@ class SSLSocketStream final : public Stream {
32513255};
32523256#endif
32533257
3258+ inline bool keep_alive (const std::atomic<socket_t > &svr_sock, socket_t sock,
3259+ time_t keep_alive_timeout_sec) {
3260+ using namespace std ::chrono;
3261+
3262+ const auto interval_usec =
3263+ CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND;
3264+
3265+ // Avoid expensive `steady_clock::now()` call for the first time
3266+ if (select_read (sock, 0 , interval_usec) > 0 ) { return true ; }
3267+
3268+ const auto start = steady_clock::now () - microseconds{interval_usec};
3269+ const auto timeout = seconds{keep_alive_timeout_sec};
3270+
3271+ while (true ) {
3272+ if (svr_sock == INVALID_SOCKET) {
3273+ break ; // Server socket is closed
3274+ }
3275+
3276+ auto val = select_read (sock, 0 , interval_usec);
3277+ if (val < 0 ) {
3278+ break ; // Ssocket error
3279+ } else if (val == 0 ) {
3280+ if (steady_clock::now () - start > timeout) {
3281+ break ; // Timeout
3282+ }
3283+ } else {
3284+ return true ; // Ready for read
3285+ }
3286+
3287+ std::this_thread::sleep_for (microseconds{interval_usec});
3288+ }
3289+
3290+ return false ;
3291+ }
3292+
32543293template <typename T>
32553294inline bool
32563295process_server_socket_core (const std::atomic<socket_t > &svr_sock, socket_t sock,
@@ -3259,8 +3298,7 @@ process_server_socket_core(const std::atomic<socket_t> &svr_sock, socket_t sock,
32593298 assert (keep_alive_max_count > 0 );
32603299 auto ret = false ;
32613300 auto count = keep_alive_max_count;
3262- while (svr_sock != INVALID_SOCKET && count > 0 &&
3263- select_read (sock, keep_alive_timeout_sec, 0 ) > 0 ) {
3301+ while (count > 0 && keep_alive (svr_sock, sock, keep_alive_timeout_sec)) {
32643302 auto close_connection = count == 1 ;
32653303 auto connection_closed = false ;
32663304 ret = callback (close_connection, connection_closed);
0 commit comments