libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 77826187692f84b2fd9c85c42d2e8fe49935a681
parent 6dd259d216c14ddd99b2b9b96beddfd1153b7387
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 19 Jun 2012 17:47:11 +0000

Mike Crowe sends this patch:

Change various uses of time(NULL) to new MHD_monotonic_time() function to
make timeouts immune to the system real time clock changing. Leave one call
to time(2) which continues to use the real time for the HTTP Date: header.

If clock_gettime does not support CLOCK_MONOTONIC then fall through to
calling time(NULL) instead. This will be problematic if clock_gettime
sometimes fails and sometimes succeeds but that shouldn't happen.

The autoconf magic was lifted from
http://lists.gnu.org/archive/html/autoconf/2010-08/msg00035.html



Diffstat:
MChangeLog | 4++++
Mconfigure.ac | 3+++
Msrc/daemon/connection.c | 6+++---
Msrc/daemon/connection_https.c | 4++--
Msrc/daemon/daemon.c | 7+++----
Msrc/daemon/digestauth.c | 4++--
Msrc/daemon/internal.c | 10++++++++++
Msrc/daemon/internal.h | 6++++++
8 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Tue Jun 19 19:44:53 CEST 2012 + Change various uses of time(NULL) to new MHD_monotonic_time() function to + make timeouts immune to the system real time clock changing. -MC + Tue Jun 12 21:35:00 CEST 2012 Adding 451 status code. -CG diff --git a/configure.ac b/configure.ac @@ -190,6 +190,9 @@ AC_CHECK_HEADERS([plibc.h],our_private_plibc_h=0,our_private_plibc_h=1) AM_CONDITIONAL(USE_PRIVATE_PLIBC_H, test x$our_private_plibc_h = x1) AC_CHECK_FUNCS(memmem) +AC_SEARCH_LIBS([clock_gettime], [rt], [ + AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Have clock_gettime]) +]) # IPv6 AC_MSG_CHECKING(for IPv6) diff --git a/src/daemon/connection.c b/src/daemon/connection.c @@ -1786,7 +1786,7 @@ parse_connection_headers (struct MHD_Connection *connection) int MHD_connection_handle_read (struct MHD_Connection *connection) { - connection->last_activity = time (NULL); + connection->last_activity = MHD_monotonic_time(); if (connection->state == MHD_CONNECTION_CLOSED) return MHD_YES; /* make sure "read" has a reasonable number of bytes @@ -1851,7 +1851,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection) { struct MHD_Response *response; int ret; - connection->last_activity = time (NULL); + connection->last_activity = MHD_monotonic_time(); while (1) { #if DEBUG_STATES @@ -2372,7 +2372,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) } timeout = connection->connection_timeout; if ( (timeout != 0) && - (timeout <= (time (NULL) - connection->last_activity)) ) + (timeout <= (MHD_monotonic_time() - connection->last_activity)) ) { MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); return MHD_YES; diff --git a/src/daemon/connection_https.c b/src/daemon/connection_https.c @@ -47,7 +47,7 @@ run_tls_handshake (struct MHD_Connection *connection) { int ret; - connection->last_activity = time (NULL); + connection->last_activity = MHD_monotonic_time(); if (connection->state == MHD_TLS_CONNECTION_INIT) { ret = gnutls_handshake (connection->tls_session); @@ -138,7 +138,7 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection) __FUNCTION__, MHD_state_to_string (connection->state)); #endif timeout = connection->connection_timeout; - if ( (timeout != 0) && (time (NULL) - timeout > connection->last_activity)) + if ( (timeout != 0) && (MHD_monotonic_time() - timeout > connection->last_activity)) MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); switch (connection->state) diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c @@ -546,7 +546,6 @@ MHD_get_fdset (struct MHD_Daemon *daemon, return MHD_YES; } - /** * Main function of the thread that handles an individual * connection when MHD_USE_THREAD_PER_CONNECTION is set. @@ -578,7 +577,7 @@ MHD_handle_connection (void *data) tvp = NULL; if (timeout > 0) { - now = time (NULL); + now = MHD_monotonic_time(); if (now - con->last_activity > timeout) tv.tv_sec = 0; else @@ -938,7 +937,7 @@ MHD_add_connection (struct MHD_Daemon *daemon, connection->addr_len = addrlen; connection->socket_fd = client_socket; connection->daemon = daemon; - connection->last_activity = time (NULL); + connection->last_activity = MHD_monotonic_time(); /* set default connection handlers */ MHD_set_http_callbacks_ (connection); @@ -1252,7 +1251,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon, } if (!have_timeout) return MHD_NO; - now = time (NULL); + now = MHD_monotonic_time(); if (earliest_deadline < now) *timeout = 0; else diff --git a/src/daemon/digestauth.c b/src/daemon/digestauth.c @@ -619,7 +619,7 @@ MHD_digest_auth_check(struct MHD_Connection *connection, /* 8 = 4 hexadecimal numbers for the timestamp */ nonce_time = strtoul(nonce + len - 8, (char **)NULL, 16); - t = (uint32_t) time(NULL); + t = (uint32_t) MHD_monotonic_time(); /* * First level vetting for the nonce validity if the timestamp * attached to the nonce exceeds `nonce_timeout' then the nonce is @@ -751,7 +751,7 @@ MHD_queue_auth_fail_response(struct MHD_Connection *connection, char nonce[HASH_MD5_HEX_LEN + 9]; /* Generating the server nonce */ - calculate_nonce ((uint32_t) time(NULL), + calculate_nonce ((uint32_t) MHD_monotonic_time(), connection->method, connection->daemon->digest_auth_random, connection->daemon->digest_auth_rand_size, diff --git a/src/daemon/internal.c b/src/daemon/internal.c @@ -157,4 +157,14 @@ MHD_http_unescape (void *cls, return wpos - val; /* = strlen(val) */ } +time_t MHD_monotonic_time(void) +{ +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + return ts.tv_sec; +#endif + return time(NULL); +} + /* end of internal.c */ diff --git a/src/daemon/internal.h b/src/daemon/internal.h @@ -1057,5 +1057,11 @@ struct MHD_Daemon (element)->next = NULL; \ (element)->prev = NULL; } while (0) +/** + * Equivalent to time(NULL) but tries to use some sort of monotonic + * clock that isn't affected by someone setting the system real time + * clock. + */ +time_t MHD_monotonic_time(void); #endif