| /* |
| This file is part of libmicrohttpd |
| Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with this library; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /** |
| * @file lib/daemon_get_timeout.c |
| * @brief function to obtain timeout for event loop |
| * @author Christian Grothoff |
| */ |
| #include "internal.h" |
| |
| |
| /** |
| * Obtain timeout value for polling function for this daemon. |
| * This function set value to amount of milliseconds for which polling |
| * function (`select()` or `poll()`) should at most block, not the |
| * timeout value set for connections. |
| * It is important to always use this function, even if connection |
| * timeout is not set, as in some cases MHD may already have more |
| * data to process on next turn (data pending in TLS buffers, |
| * connections are already ready with epoll etc.) and returned timeout |
| * will be zero. |
| * |
| * @param daemon daemon to query for timeout |
| * @param timeout set to the timeout (in milliseconds) |
| * @return #MHD_SC_OK on success, #MHD_SC_NO_TIMEOUT if timeouts are |
| * not used (or no connections exist that would |
| * necessitate the use of a timeout right now), otherwise |
| * an error code |
| * @ingroup event |
| */ |
| enum MHD_StatusCode |
| MHD_daemon_get_timeout (struct MHD_Daemon *daemon, |
| MHD_UNSIGNED_LONG_LONG *timeout) |
| { |
| time_t earliest_deadline; |
| time_t now; |
| struct MHD_Connection *pos; |
| bool have_timeout; |
| |
| if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) |
| { |
| #ifdef HAVE_MESSAGES |
| MHD_DLOG (daemon, |
| MHD_SC_CONFIGURATION_MISMATCH_FOR_GET_TIMEOUT, |
| _ ("Illegal call to MHD_get_timeout.\n")); |
| #endif |
| return MHD_SC_CONFIGURATION_MISMATCH_FOR_GET_TIMEOUT; |
| } |
| |
| if (daemon->data_already_pending) |
| { |
| /* Some data already waiting to be processed. */ |
| *timeout = 0; |
| return MHD_SC_OK; |
| } |
| |
| #ifdef EPOLL_SUPPORT |
| if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) && |
| ((NULL != daemon->eready_head) |
| #if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT) |
| || (NULL != daemon->eready_urh_head) |
| #endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */ |
| ) ) |
| { |
| /* Some connection(s) already have some data pending. */ |
| *timeout = 0; |
| return MHD_SC_OK; |
| } |
| #endif /* EPOLL_SUPPORT */ |
| |
| have_timeout = false; |
| earliest_deadline = 0; /* avoid compiler warnings */ |
| for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX) |
| { |
| if (0 != pos->connection_timeout) |
| { |
| if ( (! have_timeout) || |
| (earliest_deadline - pos->last_activity > pos->connection_timeout) ) |
| earliest_deadline = pos->last_activity + pos->connection_timeout; |
| have_timeout = true; |
| } |
| } |
| /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */ |
| pos = daemon->normal_timeout_tail; |
| if ( (NULL != pos) && |
| (0 != pos->connection_timeout) ) |
| { |
| if ( (! have_timeout) || |
| (earliest_deadline - pos->connection_timeout > pos->last_activity) ) |
| earliest_deadline = pos->last_activity + pos->connection_timeout; |
| have_timeout = true; |
| } |
| |
| if (! have_timeout) |
| return MHD_SC_NO_TIMEOUT; |
| now = MHD_monotonic_sec_counter (); |
| if (earliest_deadline < now) |
| *timeout = 0; |
| else |
| { |
| const time_t second_left = earliest_deadline - now; |
| if (second_left > ULLONG_MAX / 1000) /* Ignore compiler warning: 'second_left' is always positive. */ |
| *timeout = ULLONG_MAX; |
| else |
| *timeout = 1000LL * second_left; |
| } |
| return MHD_SC_OK; |
| } |
| |
| |
| /* end of daemon_get_timeout.c */ |