aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-02-15 07:49:56 +0100
committerChristian Grothoff <christian@grothoff.org>2018-02-15 07:49:56 +0100
commitf4355ac34bb1fad42ccb650038bddddb65d70443 (patch)
tree347140efba206b2ae15aea06aea0d4c475e63ac9
parent5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822 (diff)
downloadlibmicrohttpd-f4355ac34bb1fad42ccb650038bddddb65d70443.tar.gz
libmicrohttpd-f4355ac34bb1fad42ccb650038bddddb65d70443.zip
implement MHD_resume_suspended_connections_
-rw-r--r--src/lib/connection_add.c2
-rw-r--r--src/lib/daemon_destroy.c3
-rw-r--r--src/lib/daemon_epoll.c3
-rw-r--r--src/lib/daemon_ip_limit.c20
-rw-r--r--src/lib/daemon_poll.c5
-rw-r--r--src/lib/daemon_select.c7
-rw-r--r--src/lib/request_resume.c121
-rw-r--r--src/lib/request_resume.h43
8 files changed, 195 insertions, 9 deletions
diff --git a/src/lib/connection_add.c b/src/lib/connection_add.c
index fbd7b85f..5ce9030a 100644
--- a/src/lib/connection_add.c
+++ b/src/lib/connection_add.c
@@ -50,7 +50,7 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
50 if ( (NULL != daemon->tls_api) && 50 if ( (NULL != daemon->tls_api) &&
51 (MHD_ELS_POLL != daemon->event_loop_syscall) ) 51 (MHD_ELS_POLL != daemon->event_loop_syscall) )
52 { 52 {
53 MHD_daemon_upgrade_connection_with_select (con); 53 MHD_daemon_upgrade_connection_with_select_ (con);
54 } 54 }
55#ifdef HAVE_POLL 55#ifdef HAVE_POLL
56 else if (NULL != daemon->tls_api) 56 else if (NULL != daemon->tls_api)
diff --git a/src/lib/daemon_destroy.c b/src/lib/daemon_destroy.c
index 36f23d17..14cc0b20 100644
--- a/src/lib/daemon_destroy.c
+++ b/src/lib/daemon_destroy.c
@@ -23,6 +23,7 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "request_resume.h"
26 27
27 28
28/** 29/**
@@ -113,7 +114,7 @@ MHD_daemon_destroy (struct MHD_Daemon *daemon)
113 { 114 {
114 /* Worker daemon or single daemon with internal thread(s). */ 115 /* Worker daemon or single daemon with internal thread(s). */
115 if (! daemon->disallow_suspend_resume) 116 if (! daemon->disallow_suspend_resume)
116 resume_suspended_connections (daemon); 117 (void) MHD_resume_suspended_connections_ (daemon);
117 118
118 /* Separate thread(s) is used for polling sockets. */ 119 /* Separate thread(s) is used for polling sockets. */
119 if (MHD_ITC_IS_VALID_(daemon->itc)) 120 if (MHD_ITC_IS_VALID_(daemon->itc))
diff --git a/src/lib/daemon_epoll.c b/src/lib/daemon_epoll.c
index 1c336f41..c23a34da 100644
--- a/src/lib/daemon_epoll.c
+++ b/src/lib/daemon_epoll.c
@@ -24,6 +24,7 @@
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "daemon_epoll.h" 26#include "daemon_epoll.h"
27#include "request_resume.h"
27 28
28#ifdef EPOLL_SUPPORT 29#ifdef EPOLL_SUPPORT
29 30
@@ -301,7 +302,7 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
301 } 302 }
302 303
303 if ( (! daemon->disallow_suspend_resume) && 304 if ( (! daemon->disallow_suspend_resume) &&
304 (MHD_YES == resume_suspended_connections (daemon)) ) 305 (MHD_resume_suspended_connections_ (daemon)) )
305 may_block = false; 306 may_block = false;
306 307
307 if (may_block) 308 if (may_block)
diff --git a/src/lib/daemon_ip_limit.c b/src/lib/daemon_ip_limit.c
index f33b8193..d368893b 100644
--- a/src/lib/daemon_ip_limit.c
+++ b/src/lib/daemon_ip_limit.c
@@ -60,6 +60,22 @@ struct MHD_IPCount
60 60
61 61
62/** 62/**
63 * Trace up to and return master daemon. If the supplied daemon
64 * is a master, then return the daemon itself.
65 *
66 * @param daemon handle to a daemon
67 * @return master daemon handle
68 */
69static struct MHD_Daemon*
70get_master (struct MHD_Daemon *daemon)
71{
72 while (NULL != daemon->master)
73 daemon = daemon->master;
74 return daemon;
75}
76
77
78/**
63 * Lock shared structure for IP connection counts and connection DLLs. 79 * Lock shared structure for IP connection counts and connection DLLs.
64 * 80 *
65 * @param daemon handle to daemon where lock is 81 * @param daemon handle to daemon where lock is
@@ -172,7 +188,7 @@ MHD_ip_limit_add (struct MHD_Daemon *daemon,
172 void *node; 188 void *node;
173 int result; 189 int result;
174 190
175 daemon = MHD_get_master (daemon); 191 daemon = get_master (daemon);
176 /* Ignore if no connection limit assigned */ 192 /* Ignore if no connection limit assigned */
177 if (0 == daemon->ip_connection_limit) 193 if (0 == daemon->ip_connection_limit)
178 return MHD_YES; 194 return MHD_YES;
@@ -238,7 +254,7 @@ MHD_ip_limit_del (struct MHD_Daemon *daemon,
238 struct MHD_IPCount *found_key; 254 struct MHD_IPCount *found_key;
239 void **nodep; 255 void **nodep;
240 256
241 daemon = MHD_get_master (daemon); 257 daemon = get_master (daemon);
242 /* Ignore if no connection limit assigned */ 258 /* Ignore if no connection limit assigned */
243 if (0 == daemon->ip_connection_limit) 259 if (0 == daemon->ip_connection_limit)
244 return; 260 return;
diff --git a/src/lib/daemon_poll.c b/src/lib/daemon_poll.c
index 92093652..ba061729 100644
--- a/src/lib/daemon_poll.c
+++ b/src/lib/daemon_poll.c
@@ -23,6 +23,7 @@
23 */ 23 */
24#include "internal.h" 24#include "internal.h"
25#include "daemon_poll.h" 25#include "daemon_poll.h"
26#include "request_resume.h"
26 27
27#ifdef HAVE_POLL 28#ifdef HAVE_POLL
28 29
@@ -143,7 +144,7 @@ MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
143#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 144#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
144 145
145 if ( (! daemon->disallow_suspend_resume) && 146 if ( (! daemon->disallow_suspend_resume) &&
146 (MHD_YES == resume_suspended_connections (daemon)) ) 147 (MHD_resume_suspended_connections_ (daemon)) )
147 may_block = false; 148 may_block = false;
148 149
149 /* count number of connections and thus determine poll set size */ 150 /* count number of connections and thus determine poll set size */
@@ -385,7 +386,7 @@ MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
385 } 386 }
386 387
387 if (! daemon->disallow_suspend_resume) 388 if (! daemon->disallow_suspend_resume)
388 (void) resume_suspended_connections (daemon); 389 (void) MHD_resume_suspended_connections_ (daemon);
389 390
390 if (! may_block) 391 if (! may_block)
391 timeout = 0; 392 timeout = 0;
diff --git a/src/lib/daemon_select.c b/src/lib/daemon_select.c
index 5d8a7ecc..1f3b86ad 100644
--- a/src/lib/daemon_select.c
+++ b/src/lib/daemon_select.c
@@ -24,6 +24,8 @@
24 */ 24 */
25#include "internal.h" 25#include "internal.h"
26#include "daemon_select.h" 26#include "daemon_select.h"
27#include "request_resume.h"
28
27 29
28/** 30/**
29 * We defined a macro with the same name as a function we 31 * We defined a macro with the same name as a function we
@@ -595,6 +597,7 @@ enum MHD_StatusCode
595MHD_daemon_run_from_select (struct MHD_Daemon *daemon, 597MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
596 const fd_set *read_fd_set, 598 const fd_set *read_fd_set,
597 599
600
598 const fd_set *write_fd_set, 601 const fd_set *write_fd_set,
599 const fd_set *except_fd_set) 602 const fd_set *except_fd_set)
600{ 603{
@@ -617,7 +620,7 @@ MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
617 620
618 /* Resuming external connections when using an extern mainloop */ 621 /* Resuming external connections when using an extern mainloop */
619 if (! daemon->disallow_suspend_resume) 622 if (! daemon->disallow_suspend_resume)
620 resume_suspended_connections (daemon); 623 (void) MHD_resume_suspended_connections_ (daemon);
621 624
622 return internal_run_from_select (daemon, 625 return internal_run_from_select (daemon,
623 read_fd_set, 626 read_fd_set,
@@ -661,7 +664,7 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon,
661 maxsock = MHD_INVALID_SOCKET; 664 maxsock = MHD_INVALID_SOCKET;
662 sc = MHD_SC_OK; 665 sc = MHD_SC_OK;
663 if ( (! daemon->disallow_suspend_resume) && 666 if ( (! daemon->disallow_suspend_resume) &&
664 (MHD_YES == resume_suspended_connections (daemon)) && 667 (MHD_resume_suspended_connections_ (daemon)) &&
665 (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_model) ) 668 (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_model) )
666 may_block = MHD_NO; 669 may_block = MHD_NO;
667 670
diff --git a/src/lib/request_resume.c b/src/lib/request_resume.c
index fcb9a5a3..b632d200 100644
--- a/src/lib/request_resume.c
+++ b/src/lib/request_resume.c
@@ -62,4 +62,125 @@ MHD_request_resume (struct MHD_Request *request)
62 } 62 }
63} 63}
64 64
65
66/**
67 * Run through the suspended connections and move any that are no
68 * longer suspended back to the active state.
69 * @remark To be called only from thread that process
70 * daemon's select()/poll()/etc.
71 *
72 * @param daemon daemon context
73 * @return true if a connection was actually resumed
74 */
75bool
76MHD_resume_suspended_connections_ (struct MHD_Daemon *daemon)
77{
78 struct MHD_Connection *pos;
79 struct MHD_Connection *prev = NULL;
80 bool ret;
81 const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model);
82
83 mhd_assert (NULL == daemon->worker_pool);
84 ret = false;
85 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
86
87 if (daemon->resuming)
88 {
89 prev = daemon->suspended_connections_tail;
90 /* During shutdown check for resuming is forced. */
91 mhd_assert((NULL != prev) || (daemon->shutdown));
92 }
93
94 daemon->resuming = false;
95
96 while (NULL != (pos = prev))
97 {
98#ifdef UPGRADE_SUPPORT
99 struct MHD_UpgradeResponseHandle * const urh = pos->request.urh;
100#else /* ! UPGRADE_SUPPORT */
101 static const void * const urh = NULL;
102#endif /* ! UPGRADE_SUPPORT */
103 prev = pos->prev;
104 if ( (! pos->resuming)
105#ifdef UPGRADE_SUPPORT
106 || ( (NULL != urh) &&
107 ( (! urh->was_closed) ||
108 (! urh->clean_ready) ) )
109#endif /* UPGRADE_SUPPORT */
110 )
111 continue;
112 ret = true;
113 mhd_assert (pos->suspended);
114 DLL_remove (daemon->suspended_connections_head,
115 daemon->suspended_connections_tail,
116 pos);
117 pos->suspended = false;
118 if (NULL == urh)
119 {
120 DLL_insert (daemon->connections_head,
121 daemon->connections_tail,
122 pos);
123 if (! used_thr_p_c)
124 {
125 /* Reset timeout timer on resume. */
126 if (0 != pos->connection_timeout)
127 pos->last_activity = MHD_monotonic_sec_counter();
128
129 if (pos->connection_timeout == daemon->connection_default_timeout)
130 XDLL_insert (daemon->normal_timeout_head,
131 daemon->normal_timeout_tail,
132 pos);
133 else
134 XDLL_insert (daemon->manual_timeout_head,
135 daemon->manual_timeout_tail,
136 pos);
137 }
138#ifdef EPOLL_SUPPORT
139 if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
140 {
141 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
142 MHD_PANIC ("Resumed connection was already in EREADY set\n");
143 /* we always mark resumed connections as ready, as we
144 might have missed the edge poll event during suspension */
145 EDLL_insert (daemon->eready_head,
146 daemon->eready_tail,
147 pos);
148 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL | \
149 MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
150 pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
151 }
152#endif
153 }
154#ifdef UPGRADE_SUPPORT
155 else
156 {
157 /* Data forwarding was finished (for TLS connections) AND
158 * application was closed upgraded connection.
159 * Insert connection into cleanup list. */
160 DLL_insert (daemon->cleanup_head,
161 daemon->cleanup_tail,
162 pos);
163
164 }
165#endif /* UPGRADE_SUPPORT */
166 pos->resuming = false;
167 }
168 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
169 if ( (used_thr_p_c) &&
170 (ret) )
171 { /* Wake up suspended connections. */
172 if (! MHD_itc_activate_(daemon->itc,
173 "w"))
174 {
175#ifdef HAVE_MESSAGES
176 MHD_DLOG (daemon,
177 MHD_SC_ITC_USE_FAILED,
178 _("Failed to signal resume of connection via inter-thread communication channel."));
179#endif
180 }
181 }
182 return ret;
183}
184
185
65/* end of request_resume.c */ 186/* end of request_resume.c */
diff --git a/src/lib/request_resume.h b/src/lib/request_resume.h
new file mode 100644
index 00000000..d23ff9e8
--- /dev/null
+++ b/src/lib/request_resume.h
@@ -0,0 +1,43 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
20/**
21 * @file lib/request_resume.h
22 * @brief implementation of MHD_request_resume()
23 * @author Christian Grothoff
24 */
25
26
27#ifndef REQUEST_RESUME_H
28#define REQUEST_RESUME_H
29
30/**
31 * Run through the suspended connections and move any that are no
32 * longer suspended back to the active state.
33 * @remark To be called only from thread that process
34 * daemon's select()/poll()/etc.
35 *
36 * @param daemon daemon context
37 * @return true if a connection was actually resumed
38 */
39bool
40MHD_resume_suspended_connections_ (struct MHD_Daemon *daemon)
41 MHD_NONNULL(1);
42
43#endif