diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 113 |
1 files changed, 61 insertions, 52 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index d4064dd7..5ca612ea 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -1858,6 +1858,54 @@ thread_main_connection_upgrade (struct MHD_Connection *con) | |||
1858 | 1858 | ||
1859 | 1859 | ||
1860 | /** | 1860 | /** |
1861 | * Get maximum wait period for the connection (the amount of time left before | ||
1862 | * connection time out) | ||
1863 | * @param c the connection to check | ||
1864 | * @return the maximum wait period before the connection must be processed | ||
1865 | * again. | ||
1866 | */ | ||
1867 | static uint64_t | ||
1868 | connection_get_wait (struct MHD_Connection *c) | ||
1869 | { | ||
1870 | const uint64_t now = MHD_monotonic_msec_counter (); | ||
1871 | const uint64_t since_actv = now - c->last_activity; | ||
1872 | const uint64_t timeout = c->connection_timeout_ms; | ||
1873 | uint64_t mseconds_left; | ||
1874 | |||
1875 | mhd_assert (0 != timeout); | ||
1876 | /* Keep the next lines in sync with #connection_check_timedout() to avoid | ||
1877 | * undesired side-effects like busy-waiting. */ | ||
1878 | if (timeout < since_actv) | ||
1879 | { | ||
1880 | if (UINT64_MAX / 2 < since_actv) | ||
1881 | { | ||
1882 | const uint64_t jump_back = c->last_activity - now; | ||
1883 | /* Very unlikely that it is more than quarter-million years pause. | ||
1884 | * More likely that system clock jumps back. */ | ||
1885 | if (5000 >= jump_back) | ||
1886 | { /* Jump back is less than 5 seconds, try to recover. */ | ||
1887 | return 100; /* Set wait time to 0.1 seconds */ | ||
1888 | } | ||
1889 | /* Too large jump back */ | ||
1890 | } | ||
1891 | return 0; /* Connection has timed out */ | ||
1892 | } | ||
1893 | else if (since_actv == timeout) | ||
1894 | { | ||
1895 | /* Exact match for timeout and time from last activity. | ||
1896 | * Maybe this is just a precise match or this happens because the timer | ||
1897 | * resolution is too low. | ||
1898 | * Set wait time to 0.1 seconds to avoid busy-waiting with low | ||
1899 | * timer resolution as connection is not timed-out yet. */ | ||
1900 | return 100; | ||
1901 | } | ||
1902 | mseconds_left = timeout - since_actv; | ||
1903 | |||
1904 | return mseconds_left; | ||
1905 | } | ||
1906 | |||
1907 | |||
1908 | /** | ||
1861 | * Main function of the thread that handles an individual | 1909 | * Main function of the thread that handles an individual |
1862 | * connection when #MHD_USE_THREAD_PER_CONNECTION is set. | 1910 | * connection when #MHD_USE_THREAD_PER_CONNECTION is set. |
1863 | * | 1911 | * |
@@ -1995,35 +2043,16 @@ thread_main_handle_connection (void *data) | |||
1995 | if ( (NULL == tvp) && | 2043 | if ( (NULL == tvp) && |
1996 | (timeout > 0) ) | 2044 | (timeout > 0) ) |
1997 | { | 2045 | { |
1998 | const uint64_t since_actv = MHD_monotonic_msec_counter () | 2046 | const uint64_t mseconds_left = connection_get_wait (con); |
1999 | - con->last_activity; | 2047 | #if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC |
2000 | if (since_actv > timeout) | 2048 | if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX) |
2001 | { | 2049 | tv.tv_sec = TIMEVAL_TV_SEC_MAX; |
2002 | tv.tv_sec = 0; | ||
2003 | tv.tv_usec = 0; | ||
2004 | } | ||
2005 | else if (since_actv == timeout) | ||
2006 | { | ||
2007 | /* Exact match for timeout and time from last activity. | ||
2008 | * Maybe this is just a precise match or this happens because the timer | ||
2009 | * resolution is too low. | ||
2010 | * Set wait time to 0.1 seconds to avoid busy-waiting with low | ||
2011 | * timer resolution as connection is not yet timed-out */ | ||
2012 | tv.tv_sec = 0; | ||
2013 | tv.tv_usec = 100 * 1000; | ||
2014 | } | ||
2015 | else | 2050 | else |
2016 | { | 2051 | #endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */ |
2017 | const uint64_t mseconds_left = timeout - since_actv; | 2052 | tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000; |
2018 | #if (SIZEOF_UINT64_T - 1) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC | 2053 | |
2019 | if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX) | 2054 | tv.tv_usec = (mseconds_left % 1000) * 1000; |
2020 | tv.tv_sec = TIMEVAL_TV_SEC_MAX; | ||
2021 | else | ||
2022 | #endif /* (SIZEOF_UINT64_T - 1) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */ | ||
2023 | tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000; | ||
2024 | 2055 | ||
2025 | tv.tv_usec = (mseconds_left % 1000) * 1000; | ||
2026 | } | ||
2027 | tvp = &tv; | 2056 | tvp = &tv; |
2028 | } | 2057 | } |
2029 | if (! use_poll) | 2058 | if (! use_poll) |
@@ -3930,33 +3959,13 @@ MHD_get_timeout (struct MHD_Daemon *daemon, | |||
3930 | 3959 | ||
3931 | if (NULL != earliest_tmot_conn) | 3960 | if (NULL != earliest_tmot_conn) |
3932 | { | 3961 | { |
3933 | const uint64_t since_actv = MHD_monotonic_msec_counter () | 3962 | const uint64_t mssecond_left = connection_get_wait (earliest_tmot_conn); |
3934 | - earliest_tmot_conn->last_activity; | ||
3935 | /* Keep the next lines in sync with #MHD_connection_handle_idle() and | ||
3936 | * with #thread_main_handle_connection(). */ | ||
3937 | if (since_actv > earliest_tmot_conn->connection_timeout_ms) | ||
3938 | *timeout = 0; | ||
3939 | else if (since_actv == earliest_tmot_conn->connection_timeout_ms) | ||
3940 | { | ||
3941 | /* Exact match for timeout and time from last activity. | ||
3942 | * Maybe this is just a precise match or this happens because the timer | ||
3943 | * resolution is too low. | ||
3944 | * Set wait time to 0.1 seconds to avoid busy-waiting with low | ||
3945 | * timer resolution as connection is not yet timed-out */ | ||
3946 | *timeout = 100; | ||
3947 | } | ||
3948 | else | ||
3949 | { | ||
3950 | const uint64_t mssecond_left = earliest_tmot_conn->connection_timeout_ms | ||
3951 | - since_actv; | ||
3952 | |||
3953 | #if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG | 3963 | #if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG |
3954 | if (mssecond_left > ULLONG_MAX) | 3964 | if (mssecond_left > ULLONG_MAX) |
3955 | *timeout = ULLONG_MAX; | 3965 | *timeout = ULLONG_MAX; |
3956 | else | 3966 | else |
3957 | #endif /* UINT64 != ULLONG_MAX */ | 3967 | #endif /* UINT64 != ULLONG_MAX */ |
3958 | *timeout = (unsigned long long) mssecond_left; | 3968 | *timeout = (unsigned long long) mssecond_left; |
3959 | } | ||
3960 | return MHD_YES; | 3969 | return MHD_YES; |
3961 | } | 3970 | } |
3962 | return MHD_NO; | 3971 | return MHD_NO; |