| /* |
| 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/action_suspend.c |
| * @brief implementation of MHD_action_suspend() |
| * @author Christian Grothoff |
| */ |
| #include "internal.h" |
| |
| |
| /** |
| * The suspend action is being run. Suspend handling |
| * of the given request. |
| * |
| * @param cls NULL |
| * @param request the request to apply the action to |
| * @return #MHD_SC_OK on success |
| */ |
| static enum MHD_StatusCode |
| suspend_action (void *cls, |
| struct MHD_Request *request) |
| { |
| (void) cls; |
| struct MHD_Connection *connection = request->connection; |
| struct MHD_Daemon *daemon = connection->daemon; |
| |
| MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); |
| if (connection->resuming) |
| { |
| /* suspending again while we didn't even complete resuming yet */ |
| connection->resuming = false; |
| MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); |
| return MHD_SC_OK; |
| } |
| if (daemon->threading_mode != MHD_TM_THREAD_PER_CONNECTION) |
| { |
| if (connection->connection_timeout == |
| daemon->connection_default_timeout) |
| XDLL_remove (daemon->normal_timeout_head, |
| daemon->normal_timeout_tail, |
| connection); |
| else |
| XDLL_remove (daemon->manual_timeout_head, |
| daemon->manual_timeout_tail, |
| connection); |
| } |
| DLL_remove (daemon->connections_head, |
| daemon->connections_tail, |
| connection); |
| mhd_assert (! connection->suspended); |
| DLL_insert (daemon->suspended_connections_head, |
| daemon->suspended_connections_tail, |
| connection); |
| connection->suspended = true; |
| #ifdef EPOLL_SUPPORT |
| if (MHD_ELS_EPOLL == daemon->event_loop_syscall) |
| { |
| if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) |
| { |
| EDLL_remove (daemon->eready_head, |
| daemon->eready_tail, |
| connection); |
| connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL; |
| } |
| if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) |
| { |
| if (0 != epoll_ctl (daemon->epoll_fd, |
| EPOLL_CTL_DEL, |
| connection->socket_fd, |
| NULL)) |
| MHD_PANIC (_ ("Failed to remove FD from epoll set.\n")); |
| connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET; |
| } |
| connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED; |
| } |
| #endif |
| MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); |
| return MHD_SC_OK; |
| } |
| |
| |
| /** |
| * Suspend handling of network data for a given request. This can |
| * be used to dequeue a request from MHD's event loop for a while. |
| * |
| * If you use this API in conjunction with a internal select or a |
| * thread pool, you must set the option #MHD_USE_ITC to |
| * ensure that a resumed request is immediately processed by MHD. |
| * |
| * Suspended requests continue to count against the total number of |
| * requests allowed (per daemon, as well as per IP, if such limits |
| * are set). Suspended requests will NOT time out; timeouts will |
| * restart when the request handling is resumed. While a |
| * request is suspended, MHD will not detect disconnects by the |
| * client. |
| * |
| * The only safe time to suspend a request is from either a |
| * #MHD_RequestHeaderCallback, #MHD_UploadCallback, or a |
| * #MHD_RequestfetchResponseCallback. Suspending a request |
| * at any other time will cause an assertion failure. |
| * |
| * Finally, it is an API violation to call #MHD_daemon_stop() while |
| * having suspended requests (this will at least create memory and |
| * socket leaks or lead to undefined behavior). You must explicitly |
| * resume all requests before stopping the daemon. |
| * |
| * @return action to cause a request to be suspended. |
| */ |
| const struct MHD_Action * |
| MHD_action_suspend (void) |
| { |
| static const struct MHD_Action suspend = { |
| .action = &suspend_action, |
| .action_cls = NULL |
| }; |
| |
| return &suspend; |
| } |
| |
| |
| /* end of action_suspend.c */ |