aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c113
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 */
1867static uint64_t
1868connection_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;