aboutsummaryrefslogtreecommitdiff
path: root/src/lib/connection_call_handlers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/connection_call_handlers.c')
-rw-r--r--src/lib/connection_call_handlers.c128
1 files changed, 126 insertions, 2 deletions
diff --git a/src/lib/connection_call_handlers.c b/src/lib/connection_call_handlers.c
index 9e6276eb..bb6123eb 100644
--- a/src/lib/connection_call_handlers.c
+++ b/src/lib/connection_call_handlers.c
@@ -23,6 +23,7 @@
23 */ 23 */
24#include "internal.h" 24#include "internal.h"
25#include "connection_call_handlers.h" 25#include "connection_call_handlers.h"
26#include "connection_update_event_loop_info.h"
26#include "connection_update_last_activity.h" 27#include "connection_update_last_activity.h"
27#include "connection_close.h" 28#include "connection_close.h"
28 29
@@ -2767,6 +2768,127 @@ process_request_body (struct MHD_Request *request)
2767 2768
2768 2769
2769/** 2770/**
2771 * Clean up the state of the given connection and move it into the
2772 * clean up queue for final disposal.
2773 * @remark To be called only from thread that process connection's
2774 * recv(), send() and response.
2775 *
2776 * @param connection handle for the connection to clean up
2777 */
2778static void
2779cleanup_connection (struct MHD_Connection *connection)
2780{
2781 struct MHD_Daemon *daemon = connection->daemon;
2782
2783 if (connection->request.in_cleanup)
2784 return; /* Prevent double cleanup. */
2785 connection->request.in_cleanup = true;
2786 if (NULL != connection->request.response)
2787 {
2788 MHD_response_queue_for_destroy (connection->request.response);
2789 connection->request.response = NULL;
2790 }
2791 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2792 if (connection->suspended)
2793 {
2794 DLL_remove (daemon->suspended_connections_head,
2795 daemon->suspended_connections_tail,
2796 connection);
2797 connection->suspended = false;
2798 }
2799 else
2800 {
2801 if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_model)
2802 {
2803 if (connection->connection_timeout ==
2804 daemon->connection_default_timeout)
2805 XDLL_remove (daemon->normal_timeout_head,
2806 daemon->normal_timeout_tail,
2807 connection);
2808 else
2809 XDLL_remove (daemon->manual_timeout_head,
2810 daemon->manual_timeout_tail,
2811 connection);
2812 }
2813 DLL_remove (daemon->connections_head,
2814 daemon->connections_tail,
2815 connection);
2816 }
2817 DLL_insert (daemon->cleanup_head,
2818 daemon->cleanup_tail,
2819 connection);
2820 connection->resuming = false;
2821 connection->request.in_idle = false;
2822 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2823 if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model)
2824 {
2825 /* if we were at the connection limit before and are in
2826 thread-per-connection mode, signal the main thread
2827 to resume accepting connections */
2828 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2829 (! MHD_itc_activate_ (daemon->itc,
2830 "c")) )
2831 {
2832#ifdef HAVE_MESSAGES
2833 MHD_DLOG (daemon,
2834 MHD_SC_ITC_USE_FAILED,
2835 _("Failed to signal end of connection via inter-thread communication channel"));
2836#endif
2837 }
2838 }
2839}
2840
2841
2842#ifdef EPOLL_SUPPORT
2843/**
2844 * Perform epoll() processing, possibly moving the connection back into
2845 * the epoll() set if needed.
2846 *
2847 * @param connection connection to process
2848 * @return true if we should continue to process the
2849 * connection (not dead yet), false if it died
2850 */
2851static bool
2852connection_epoll_update_ (struct MHD_Connection *connection)
2853{
2854 struct MHD_Daemon *daemon = connection->daemon;
2855
2856 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
2857 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
2858 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2859 ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->request.event_loop_info) &&
2860 (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
2861 ( (MHD_EVENT_LOOP_INFO_READ == connection->request.event_loop_info) &&
2862 (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
2863 {
2864 /* add to epoll set */
2865 struct epoll_event event;
2866
2867 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2868 event.data.ptr = connection;
2869 if (0 != epoll_ctl (daemon->epoll_fd,
2870 EPOLL_CTL_ADD,
2871 connection->socket_fd,
2872 &event))
2873 {
2874#ifdef HAVE_MESSAGES
2875 MHD_DLOG (daemon,
2876 MHD_SC_EPOLL_CTL_ADD_FAILED,
2877 _("Call to epoll_ctl failed: %s\n"),
2878 MHD_socket_last_strerr_ ());
2879#endif
2880 connection->request.state = MHD_REQUEST_CLOSED;
2881 cleanup_connection (connection);
2882 return false;
2883 }
2884 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2885 }
2886 return true;
2887}
2888#endif
2889
2890
2891/**
2770 * This function was created to handle per-request processing that 2892 * This function was created to handle per-request processing that
2771 * has to happen even if the socket cannot be read or written to. 2893 * has to happen even if the socket cannot be read or written to.
2772 * @remark To be called only from thread that process request's 2894 * @remark To be called only from thread that process request's
@@ -3064,6 +3186,7 @@ MHD_request_handle_idle_ (struct MHD_Request *request)
3064 { 3186 {
3065 socket_start_normal_buffering (connection); 3187 socket_start_normal_buffering (connection);
3066 request->state = MHD_REQUEST_UPGRADE; 3188 request->state = MHD_REQUEST_UPGRADE;
3189#if FIXME_LEGACY_STYLE
3067 /* This request is "upgraded". Pass socket to application. */ 3190 /* This request is "upgraded". Pass socket to application. */
3068 if (! MHD_response_execute_upgrade_ (request->response, 3191 if (! MHD_response_execute_upgrade_ (request->response,
3069 request)) 3192 request))
@@ -3074,6 +3197,7 @@ MHD_request_handle_idle_ (struct MHD_Request *request)
3074 NULL); 3197 NULL);
3075 continue; 3198 continue;
3076 } 3199 }
3200#endif
3077 /* Response is not required anymore for this request. */ 3201 /* Response is not required anymore for this request. */
3078 if (NULL != request->response) 3202 if (NULL != request->response)
3079 { 3203 {
@@ -3262,13 +3386,13 @@ MHD_request_handle_idle_ (struct MHD_Request *request)
3262 return true; 3386 return true;
3263 } 3387 }
3264 } 3388 }
3265 MHD_connection_update_event_loop_info (connection); 3389 MHD_connection_update_event_loop_info_ (connection);
3266 ret = true; 3390 ret = true;
3267#ifdef EPOLL_SUPPORT 3391#ifdef EPOLL_SUPPORT
3268 if ( (! connection->suspended) && 3392 if ( (! connection->suspended) &&
3269 (MHD_ELS_EPOLL == daemon->event_loop_syscall) ) 3393 (MHD_ELS_EPOLL == daemon->event_loop_syscall) )
3270 { 3394 {
3271 ret = MHD_connection_epoll_update_ (connection); 3395 ret = connection_epoll_update_ (connection);
3272 } 3396 }
3273#endif /* EPOLL_SUPPORT */ 3397#endif /* EPOLL_SUPPORT */
3274 request->in_idle = false; 3398 request->in_idle = false;