diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-02-15 07:49:56 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-02-15 07:49:56 +0100 |
commit | f4355ac34bb1fad42ccb650038bddddb65d70443 (patch) | |
tree | 347140efba206b2ae15aea06aea0d4c475e63ac9 | |
parent | 5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822 (diff) | |
download | libmicrohttpd-f4355ac34bb1fad42ccb650038bddddb65d70443.tar.gz libmicrohttpd-f4355ac34bb1fad42ccb650038bddddb65d70443.zip |
implement MHD_resume_suspended_connections_
-rw-r--r-- | src/lib/connection_add.c | 2 | ||||
-rw-r--r-- | src/lib/daemon_destroy.c | 3 | ||||
-rw-r--r-- | src/lib/daemon_epoll.c | 3 | ||||
-rw-r--r-- | src/lib/daemon_ip_limit.c | 20 | ||||
-rw-r--r-- | src/lib/daemon_poll.c | 5 | ||||
-rw-r--r-- | src/lib/daemon_select.c | 7 | ||||
-rw-r--r-- | src/lib/request_resume.c | 121 | ||||
-rw-r--r-- | src/lib/request_resume.h | 43 |
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 | */ | ||
69 | static struct MHD_Daemon* | ||
70 | get_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 | |||
595 | MHD_daemon_run_from_select (struct MHD_Daemon *daemon, | 597 | MHD_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 | */ | ||
75 | bool | ||
76 | MHD_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 | */ | ||
39 | bool | ||
40 | MHD_resume_suspended_connections_ (struct MHD_Daemon *daemon) | ||
41 | MHD_NONNULL(1); | ||
42 | |||
43 | #endif | ||