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/daemon_epoll.c
22 * @brief functions to run epoll()-based event loop
23 * @author Christian Grothoff
24 */
25 #include "internal.h"
26 #include "connection_add.h"
27 #include "connection_call_handlers.h"
28 #include "connection_finish_forward.h"
29 #include "daemon_epoll.h"
30 #include "upgrade_process.h"
31 #include "request_resume.h"
32
33 #ifdef EPOLL_SUPPORT
34
35 /**
36 * How many events to we process at most per epoll() call? Trade-off
37 * between required stack-size and number of system calls we have to
38 * make; 128 should be way enough to avoid more than one system call
39 * for most scenarios, and still be moderate in stack size
40 * consumption. Embedded systems might want to choose a smaller value
41 * --- but why use epoll() on such a system in the first place?
42 */
43 #define MAX_EVENTS 128
44
45
46 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
47
48 /**
49 * Checks whether @a urh has some data to process.
50 *
51 * @param urh upgrade handler to analyse
52 * @return 'true' if @a urh has some data to process,
53 * 'false' otherwise
54 */
55 static bool
is_urh_ready(struct MHD_UpgradeResponseHandle * const urh)56 is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
57 {
58 const struct MHD_Connection *const connection = urh->connection;
59
60 if ( (0 == urh->in_buffer_size) &&
61 (0 == urh->out_buffer_size) &&
62 (0 == urh->in_buffer_used) &&
63 (0 == urh->out_buffer_used) )
64 return false;
65
66 if (connection->daemon->shutdown)
67 return true;
68
69 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
70 (connection->tls_read_ready) ) &&
71 (urh->in_buffer_used < urh->in_buffer_size) )
72 return true;
73
74 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
75 (urh->out_buffer_used < urh->out_buffer_size) )
76 return true;
77
78 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
79 (urh->out_buffer_used > 0) )
80 return true;
81
82 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
83 (urh->in_buffer_used > 0) )
84 return true;
85
86 return false;
87 }
88
89
90 /**
91 * Do epoll()-based processing for TLS connections that have been
92 * upgraded. This requires a separate epoll() invocation as we
93 * cannot use the `struct MHD_Connection` data structures for
94 * the `union epoll_data` in this case.
95 * @remark To be called only from thread that process
96 * daemon's select()/poll()/etc.
97 *
98 * @param daemon the daemmon for which we process connections
99 * @return #MHD_SC_OK on success
100 */
101 static enum MHD_StatusCode
run_epoll_for_upgrade(struct MHD_Daemon * daemon)102 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
103 {
104 struct epoll_event events[MAX_EVENTS];
105 int num_events;
106 struct MHD_UpgradeResponseHandle *pos;
107 struct MHD_UpgradeResponseHandle *prev;
108
109 num_events = MAX_EVENTS;
110 while (MAX_EVENTS == num_events)
111 {
112 unsigned int i;
113
114 /* update event masks */
115 num_events = epoll_wait (daemon->epoll_upgrade_fd,
116 events,
117 MAX_EVENTS,
118 0);
119 if (-1 == num_events)
120 {
121 const int err = MHD_socket_get_error_ ();
122 if (MHD_SCKT_ERR_IS_EINTR_ (err))
123 return MHD_SC_OK;
124 #ifdef HAVE_MESSAGES
125 MHD_DLOG (daemon,
126 MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR,
127 _ ("Call to epoll_wait failed: %s\n"),
128 MHD_socket_strerr_ (err));
129 #endif
130 return MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR;
131 }
132 for (i = 0; i < (unsigned int) num_events; i++)
133 {
134 struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
135 struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
136 bool new_err_state = false;
137
138 if (urh->clean_ready)
139 continue;
140
141 /* Update ueh state based on what is ready according to epoll() */
142 if (0 != (events[i].events & EPOLLIN))
143 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
144 if (0 != (events[i].events & EPOLLOUT))
145 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
146 if (0 != (events[i].events & EPOLLHUP))
147 ueh->celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
148
149 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
150 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
151 {
152 /* Process new error state only one time
153 * and avoid continuously marking this connection
154 * as 'ready'. */
155 ueh->celi |= MHD_EPOLL_STATE_ERROR;
156 new_err_state = true;
157 }
158
159 if (! urh->in_eready_list)
160 {
161 if (new_err_state ||
162 is_urh_ready (urh))
163 {
164 EDLL_insert (daemon->eready_urh_head,
165 daemon->eready_urh_tail,
166 urh);
167 urh->in_eready_list = true;
168 }
169 }
170 }
171 }
172 prev = daemon->eready_urh_tail;
173 while (NULL != (pos = prev))
174 {
175 prev = pos->prevE;
176 MHD_upgrade_response_handle_process_ (pos);
177 if (! is_urh_ready (pos))
178 {
179 EDLL_remove (daemon->eready_urh_head,
180 daemon->eready_urh_tail,
181 pos);
182 pos->in_eready_list = false;
183 }
184 /* Finished forwarding? */
185 if ( (0 == pos->in_buffer_size) &&
186 (0 == pos->out_buffer_size) &&
187 (0 == pos->in_buffer_used) &&
188 (0 == pos->out_buffer_used) )
189 {
190 MHD_connection_finish_forward_ (pos->connection);
191 pos->clean_ready = true;
192 /* If 'pos->was_closed' already was set to true, connection
193 * will be moved immediately to cleanup list. Otherwise
194 * connection will stay in suspended list until 'pos' will
195 * be marked with 'was_closed' by application. */
196 MHD_request_resume (&pos->connection->request);
197 }
198 }
199
200 return MHD_SC_OK;
201 }
202
203
204 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
205
206
207 /**
208 * Do epoll()-based processing (this function is allowed to
209 * block if @a may_block is set to #MHD_YES).
210 *
211 * @param daemon daemon to run poll loop for
212 * @param may_block true if blocking, false if non-blocking
213 * @return #MHD_SC_OK on success
214 */
215 enum MHD_StatusCode
MHD_daemon_epoll_(struct MHD_Daemon * daemon,bool may_block)216 MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
217 bool may_block)
218 {
219 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
220 static const char *const upgrade_marker = "upgrade_ptr";
221 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
222 struct MHD_Connection *pos;
223 struct MHD_Connection *prev;
224 struct epoll_event events[MAX_EVENTS];
225 struct epoll_event event;
226 int timeout_ms;
227 MHD_UNSIGNED_LONG_LONG timeout_ll;
228 int num_events;
229 unsigned int i;
230 MHD_socket ls;
231 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
232 bool run_upgraded = false;
233 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
234
235 if (-1 == daemon->epoll_fd)
236 return MHD_SC_EPOLL_FD_INVALID; /* we're down! */
237 if (daemon->shutdown)
238 return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
239 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
240 (! daemon->was_quiesced) &&
241 (daemon->connections < daemon->global_connection_limit) &&
242 (! daemon->listen_socket_in_epoll) &&
243 (! daemon->at_limit) )
244 {
245 event.events = EPOLLIN;
246 event.data.ptr = daemon;
247 if (0 != epoll_ctl (daemon->epoll_fd,
248 EPOLL_CTL_ADD,
249 ls,
250 &event))
251 {
252 #ifdef HAVE_MESSAGES
253 MHD_DLOG (daemon,
254 MHD_SC_EPOLL_CTL_ADD_FAILED,
255 _ ("Call to epoll_ctl failed: %s\n"),
256 MHD_socket_last_strerr_ ());
257 #endif
258 return MHD_SC_EPOLL_CTL_ADD_FAILED;
259 }
260 daemon->listen_socket_in_epoll = true;
261 }
262 if ( (daemon->was_quiesced) &&
263 (daemon->listen_socket_in_epoll) )
264 {
265 if (0 != epoll_ctl (daemon->epoll_fd,
266 EPOLL_CTL_DEL,
267 ls,
268 NULL))
269 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
270 daemon->listen_socket_in_epoll = false;
271 }
272
273 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
274 if ( (! daemon->upgrade_fd_in_epoll) &&
275 (-1 != daemon->epoll_upgrade_fd) )
276 {
277 event.events = EPOLLIN | EPOLLOUT;
278 event.data.ptr = (void *) upgrade_marker;
279 if (0 != epoll_ctl (daemon->epoll_fd,
280 EPOLL_CTL_ADD,
281 daemon->epoll_upgrade_fd,
282 &event))
283 {
284 #ifdef HAVE_MESSAGES
285 MHD_DLOG (daemon,
286 MHD_SC_EPOLL_CTL_ADD_FAILED,
287 _ ("Call to epoll_ctl failed: %s\n"),
288 MHD_socket_last_strerr_ ());
289 #endif
290 return MHD_SC_EPOLL_CTL_ADD_FAILED;
291 }
292 daemon->upgrade_fd_in_epoll = true;
293 }
294 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
295 if ( (daemon->listen_socket_in_epoll) &&
296 ( (daemon->connections == daemon->global_connection_limit) ||
297 (daemon->at_limit) ||
298 (daemon->was_quiesced) ) )
299 {
300 /* we're at the connection limit, disable listen socket
301 for event loop for now */
302 if (0 != epoll_ctl (daemon->epoll_fd,
303 EPOLL_CTL_DEL,
304 ls,
305 NULL))
306 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
307 daemon->listen_socket_in_epoll = false;
308 }
309
310 if ( (! daemon->disallow_suspend_resume) &&
311 (MHD_resume_suspended_connections_ (daemon)) )
312 may_block = false;
313
314 if (may_block)
315 {
316 if (MHD_SC_OK == /* FIXME: distinguish between NO_TIMEOUT and errors */
317 MHD_daemon_get_timeout (daemon,
318 &timeout_ll))
319 {
320 if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
321 timeout_ms = INT_MAX;
322 else
323 timeout_ms = (int) timeout_ll;
324 }
325 else
326 timeout_ms = -1;
327 }
328 else
329 timeout_ms = 0;
330
331 /* Reset. New value will be set when connections are processed. */
332 /* Note: Used mostly for uniformity here as same situation is
333 * signaled in epoll mode by non-empty eready DLL. */
334 daemon->data_already_pending = false;
335
336 /* drain 'epoll' event queue; need to iterate as we get at most
337 MAX_EVENTS in one system call here; in practice this should
338 pretty much mean only one round, but better an extra loop here
339 than unfair behavior... */
340 num_events = MAX_EVENTS;
341 while (MAX_EVENTS == num_events)
342 {
343 /* update event masks */
344 num_events = epoll_wait (daemon->epoll_fd,
345 events,
346 MAX_EVENTS,
347 timeout_ms);
348 if (-1 == num_events)
349 {
350 const int err = MHD_socket_get_error_ ();
351 if (MHD_SCKT_ERR_IS_EINTR_ (err))
352 return MHD_SC_OK;
353 #ifdef HAVE_MESSAGES
354 MHD_DLOG (daemon,
355 MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR,
356 _ ("Call to epoll_wait failed: %s\n"),
357 MHD_socket_strerr_ (err));
358 #endif
359 return MHD_SC_UNEXPECTED_EPOLL_WAIT_ERROR;
360 }
361 for (i = 0; i < (unsigned int) num_events; i++)
362 {
363 /* First, check for the values of `ptr` that would indicate
364 that this event is not about a normal connection. */
365 if (NULL == events[i].data.ptr)
366 continue; /* shutdown signal! */
367 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
368 if (upgrade_marker == events[i].data.ptr)
369 {
370 /* activity on an upgraded connection, we process
371 those in a separate epoll() */
372 run_upgraded = true;
373 continue;
374 }
375 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
376 if (daemon->epoll_itc_marker == events[i].data.ptr)
377 {
378 /* It's OK to clear ITC here as all external
379 conditions will be processed later. */
380 MHD_itc_clear_ (daemon->itc);
381 continue;
382 }
383 if (daemon == events[i].data.ptr)
384 {
385 /* Check for error conditions on listen socket. */
386 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
387 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
388 {
389 unsigned int series_length = 0;
390 /* Run 'accept' until it fails or daemon at limit of connections.
391 * Do not accept more then 10 connections at once. The rest will
392 * be accepted on next turn (level trigger is used for listen
393 * socket). */
394 while ( (MHD_SC_OK ==
395 MHD_accept_connection_ (daemon)) &&
396 (series_length < 10) &&
397 (daemon->connections < daemon->global_connection_limit) &&
398 (! daemon->at_limit) )
399 series_length++;
400 }
401 continue;
402 }
403 /* this is an event relating to a 'normal' connection,
404 remember the event and if appropriate mark the
405 connection as 'eready'. */
406 pos = events[i].data.ptr;
407 /* normal processing: update read/write data */
408 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
409 {
410 pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
411 if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
412 {
413 EDLL_insert (daemon->eready_head,
414 daemon->eready_tail,
415 pos);
416 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
417 }
418 }
419 else
420 {
421 if (0 != (events[i].events & EPOLLIN))
422 {
423 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
424 if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->request.event_loop_info) ||
425 (pos->request.read_buffer_size >
426 pos->request.read_buffer_offset) ) &&
427 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
428 {
429 EDLL_insert (daemon->eready_head,
430 daemon->eready_tail,
431 pos);
432 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
433 }
434 }
435 if (0 != (events[i].events & EPOLLOUT))
436 {
437 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
438 if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->request.event_loop_info) &&
439 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
440 {
441 EDLL_insert (daemon->eready_head,
442 daemon->eready_tail,
443 pos);
444 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
445 }
446 }
447 }
448 }
449 }
450
451 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
452 if (run_upgraded)
453 run_epoll_for_upgrade (daemon); /* FIXME: return value? */
454 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
455
456 /* process events for connections */
457 prev = daemon->eready_tail;
458 while (NULL != (pos = prev))
459 {
460 prev = pos->prevE;
461 MHD_connection_call_handlers_ (pos,
462 0 != (pos->epoll_state
463 & MHD_EPOLL_STATE_READ_READY),
464 0 != (pos->epoll_state
465 & MHD_EPOLL_STATE_WRITE_READY),
466 0 != (pos->epoll_state
467 & MHD_EPOLL_STATE_ERROR));
468 if (MHD_EPOLL_STATE_IN_EREADY_EDLL ==
469 (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
470 | MHD_EPOLL_STATE_IN_EREADY_EDLL)))
471 {
472 if ( ((MHD_EVENT_LOOP_INFO_READ == pos->request.event_loop_info) &&
473 (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
474 ((MHD_EVENT_LOOP_INFO_WRITE == pos->request.event_loop_info) &&
475 (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
476 (MHD_EVENT_LOOP_INFO_CLEANUP == pos->request.event_loop_info) )
477 {
478 EDLL_remove (daemon->eready_head,
479 daemon->eready_tail,
480 pos);
481 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
482 }
483 }
484 }
485
486 /* Finally, handle timed-out connections; we need to do this here
487 as the epoll mechanism won't call the 'MHD_request_handle_idle_()' on everything,
488 as the other event loops do. As timeouts do not get an explicit
489 event, we need to find those connections that might have timed out
490 here.
491
492 Connections with custom timeouts must all be looked at, as we
493 do not bother to sort that (presumably very short) list. */prev = daemon->manual_timeout_tail;
494 while (NULL != (pos = prev))
495 {
496 prev = pos->prevX;
497 MHD_request_handle_idle_ (&pos->request);
498 }
499 /* Connections with the default timeout are sorted by prepending
500 them to the head of the list whenever we touch the connection;
501 thus it suffices to iterate from the tail until the first
502 connection is NOT timed out */
503 prev = daemon->normal_timeout_tail;
504 while (NULL != (pos = prev))
505 {
506 prev = pos->prevX;
507 MHD_request_handle_idle_ (&pos->request);
508 if (MHD_REQUEST_CLOSED != pos->request.state)
509 break; /* sorted by timeout, no need to visit the rest! */
510 }
511 return MHD_SC_OK;
512 }
513
514
515 #endif
516
517 /* end of daemon_epoll.c */
518