GNU libmicrohttpd  0.9.72
daemon_select.c
Go to the documentation of this file.
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 
25 #include "internal.h"
26 #include "connection_add.h"
28 #include "connection_cleanup.h"
30 #include "daemon_select.h"
31 #include "daemon_epoll.h"
32 #include "request_resume.h"
33 #include "upgrade_process.h"
34 
35 
41 #undef MHD_daemon_get_fdset
42 
67 enum MHD_StatusCode
68 MHD_daemon_get_fdset (struct MHD_Daemon *daemon,
69  fd_set *read_fd_set,
70  fd_set *write_fd_set,
71  fd_set *except_fd_set,
72  MHD_socket *max_fd)
73 {
74  return MHD_daemon_get_fdset2 (daemon,
75  read_fd_set,
76  write_fd_set,
77  except_fd_set,
78  max_fd,
80 }
81 
82 
83 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
96 static bool
97 urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
98  fd_set *rs,
99  fd_set *ws,
100  fd_set *es,
101  MHD_socket *max_fd,
102  unsigned int fd_setsize)
103 {
104  const MHD_socket conn_sckt = urh->connection->socket_fd;
105  const MHD_socket mhd_sckt = urh->mhd.socket;
106  bool res = true;
107 
108  /* Do not add to 'es' only if socket is closed
109  * or not used anymore. */
110  if (MHD_INVALID_SOCKET != conn_sckt)
111  {
112  if ( (urh->in_buffer_used < urh->in_buffer_size) &&
113  (! MHD_add_to_fd_set_ (conn_sckt,
114  rs,
115  max_fd,
116  fd_setsize)) )
117  res = false;
118  if ( (0 != urh->out_buffer_used) &&
119  (! MHD_add_to_fd_set_ (conn_sckt,
120  ws,
121  max_fd,
122  fd_setsize)) )
123  res = false;
124  /* Do not monitor again for errors if error was detected before as
125  * error state is remembered. */
126  if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
127  ((0 != urh->in_buffer_size) ||
128  (0 != urh->out_buffer_size) ||
129  (0 != urh->out_buffer_used)))
130  MHD_add_to_fd_set_ (conn_sckt,
131  es,
132  max_fd,
133  fd_setsize);
134  }
135  if (MHD_INVALID_SOCKET != mhd_sckt)
136  {
137  if ( (urh->out_buffer_used < urh->out_buffer_size) &&
138  (! MHD_add_to_fd_set_ (mhd_sckt,
139  rs,
140  max_fd,
141  fd_setsize)) )
142  res = false;
143  if ( (0 != urh->in_buffer_used) &&
144  (! MHD_add_to_fd_set_ (mhd_sckt,
145  ws,
146  max_fd,
147  fd_setsize)) )
148  res = false;
149  /* Do not monitor again for errors if error was detected before as
150  * error state is remembered. */
151  if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
152  ((0 != urh->out_buffer_size) ||
153  (0 != urh->in_buffer_size) ||
154  (0 != urh->in_buffer_used)))
155  MHD_add_to_fd_set_ (mhd_sckt,
156  es,
157  max_fd,
158  fd_setsize);
159  }
160 
161  return res;
162 }
163 
164 
165 #endif
166 
167 
181 static enum MHD_StatusCode
182 internal_get_fdset2 (struct MHD_Daemon *daemon,
183  fd_set *read_fd_set,
184  fd_set *write_fd_set,
185  fd_set *except_fd_set,
186  MHD_socket *max_fd,
187  unsigned int fd_setsize)
188 
189 {
190  struct MHD_Connection *pos;
191  struct MHD_Connection *posn;
192  enum MHD_StatusCode result = MHD_SC_OK;
193  MHD_socket ls;
194 
195  if (daemon->shutdown)
196  return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
197 
198  ls = daemon->listen_socket;
199  if ( (MHD_INVALID_SOCKET != ls) &&
200  (! daemon->was_quiesced) &&
201  (! MHD_add_to_fd_set_ (ls,
202  read_fd_set,
203  max_fd,
204  fd_setsize)) )
205  result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
206 
207  /* Add all sockets to 'except_fd_set' as well to watch for
208  * out-of-band data. However, ignore errors if INFO_READ
209  * or INFO_WRITE sockets will not fit 'except_fd_set'. */
210  /* Start from oldest connections. Make sense for W32 FDSETs. */
211  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
212  {
213  posn = pos->prev;
214 
215  switch (pos->request.event_loop_info)
216  {
218  if (! MHD_add_to_fd_set_ (pos->socket_fd,
219  read_fd_set,
220  max_fd,
221  fd_setsize))
222  result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
223 #ifdef MHD_POSIX_SOCKETS
225  except_fd_set,
226  max_fd,
227  fd_setsize);
228 #endif /* MHD_POSIX_SOCKETS */
229  break;
231  if (! MHD_add_to_fd_set_ (pos->socket_fd,
232  write_fd_set,
233  max_fd,
234  fd_setsize))
235  result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
236 #ifdef MHD_POSIX_SOCKETS
238  except_fd_set,
239  max_fd,
240  fd_setsize);
241 #endif /* MHD_POSIX_SOCKETS */
242  break;
244  if ( (NULL == except_fd_set) ||
246  except_fd_set,
247  max_fd,
248  fd_setsize))
249  result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
250  break;
252  /* this should never happen */
253  break;
254  }
255  }
256 #ifdef MHD_WINSOCK_SOCKETS
257  /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
258  * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
259  * not be pushed out. */
260  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
261  {
262  posn = pos->prev;
264  except_fd_set,
265  max_fd,
266  fd_setsize);
267  }
268 #endif /* MHD_WINSOCK_SOCKETS */
269 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
270  {
271  struct MHD_UpgradeResponseHandle *urh;
272 
273  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
274  {
275  if (! urh_to_fdset (urh,
276  read_fd_set,
277  write_fd_set,
278  except_fd_set,
279  max_fd,
280  fd_setsize))
281  result = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
282  }
283  }
284 #endif
285  return result;
286 }
287 
288 
316 enum MHD_StatusCode
317 MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon,
318  fd_set *read_fd_set,
319  fd_set *write_fd_set,
320  fd_set *except_fd_set,
321  MHD_socket *max_fd,
322  unsigned int fd_setsize)
323 {
324  if ( (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) ||
325  (MHD_ELS_POLL == daemon->event_loop_syscall) )
326  return MHD_SC_CONFIGURATION_MISMATCH_FOR_GET_FDSET;
327 
328 #ifdef EPOLL_SUPPORT
329  if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
330  {
331  if (daemon->shutdown)
332  return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
333 
334  /* we're in epoll mode, use the epoll FD as a stand-in for
335  the entire event set */
336 
337  return MHD_add_to_fd_set_ (daemon->epoll_fd,
338  read_fd_set,
339  max_fd,
340  fd_setsize)
341  ? MHD_SC_OK
342  : MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
343  }
344 #endif
345 
346  return internal_get_fdset2 (daemon,
347  read_fd_set,
348  write_fd_set,
349  except_fd_set,
350  max_fd,
351  fd_setsize);
352 }
353 
354 
355 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
365 static void
366 urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
367  const fd_set *rs,
368  const fd_set *ws,
369  const fd_set *es)
370 {
371  const MHD_socket conn_sckt = urh->connection->socket_fd;
372  const MHD_socket mhd_sckt = urh->mhd.socket;
373 
374  /* Reset read/write ready, preserve error state. */
377 
378  if (MHD_INVALID_SOCKET != conn_sckt)
379  {
380  if (FD_ISSET (conn_sckt, rs))
381  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
382  if (FD_ISSET (conn_sckt, ws))
383  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
384  if (FD_ISSET (conn_sckt, es))
385  urh->app.celi |= MHD_EPOLL_STATE_ERROR;
386  }
387  if ((MHD_INVALID_SOCKET != mhd_sckt))
388  {
389  if (FD_ISSET (mhd_sckt, rs))
390  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
391  if (FD_ISSET (mhd_sckt, ws))
392  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
393  if (FD_ISSET (mhd_sckt, es))
394  urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
395  }
396 }
397 
398 
399 #endif
400 
401 
412 static enum MHD_StatusCode
413 internal_run_from_select (struct MHD_Daemon *daemon,
414  const fd_set *read_fd_set,
415  const fd_set *write_fd_set,
416  const fd_set *except_fd_set)
417 {
418  MHD_socket ds;
419  struct MHD_Connection *pos;
420  struct MHD_Connection *prev;
421 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
422  struct MHD_UpgradeResponseHandle *urh;
423  struct MHD_UpgradeResponseHandle *urhn;
424 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
425  /* Reset. New value will be set when connections are processed. */
426  /* Note: no-op for thread-per-connection as it is always false in that mode. */
427  daemon->data_already_pending = false;
428 
429  /* Clear ITC to avoid spinning select */
430  /* Do it before any other processing so new signals
431  will trigger select again and will be processed */
432  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
433  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
434  read_fd_set)) )
435  MHD_itc_clear_ (daemon->itc);
436 
437  /* select connection thread handling type */
438  if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_socket)) &&
439  (! daemon->was_quiesced) &&
440  (FD_ISSET (ds,
441  read_fd_set)) )
442  (void) MHD_accept_connection_ (daemon);
443 
444  if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
445  {
446  /* do not have a thread per connection, process all connections now */
447  prev = daemon->connections_tail;
448  while (NULL != (pos = prev))
449  {
450  prev = pos->prev;
451  ds = pos->socket_fd;
452  if (MHD_INVALID_SOCKET == ds)
453  continue;
455  FD_ISSET (ds,
456  read_fd_set),
457  FD_ISSET (ds,
458  write_fd_set),
459  FD_ISSET (ds,
460  except_fd_set));
461  }
462  }
463 
464 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
465  /* handle upgraded HTTPS connections */
466  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
467  {
468  urhn = urh->prev;
469  /* update urh state based on select() output */
470  urh_from_fdset (urh,
471  read_fd_set,
472  write_fd_set,
473  except_fd_set);
474  /* call generic forwarding function for passing data */
475  MHD_upgrade_response_handle_process_ (urh);
476  /* Finished forwarding? */
477  if ( (0 == urh->in_buffer_size) &&
478  (0 == urh->out_buffer_size) &&
479  (0 == urh->in_buffer_used) &&
480  (0 == urh->out_buffer_used) )
481  {
482  MHD_connection_finish_forward_ (urh->connection);
483  urh->clean_ready = true;
484  /* Resuming will move connection to cleanup list. */
485  MHD_request_resume (&urh->connection->request);
486  }
487  }
488 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
489  MHD_connection_cleanup_ (daemon);
490  return MHD_SC_OK;
491 }
492 
493 
494 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
501 void
502 MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con)
503 {
504  struct MHD_UpgradeResponseHandle *urh = con->request.urh;
505 
506  while ( (0 != urh->in_buffer_size) ||
507  (0 != urh->out_buffer_size) ||
508  (0 != urh->in_buffer_used) ||
509  (0 != urh->out_buffer_used) )
510  {
511  /* use select */
512  fd_set rs;
513  fd_set ws;
514  fd_set es;
515  MHD_socket max_fd;
516  int num_ready;
517  bool result;
518 
519  FD_ZERO (&rs);
520  FD_ZERO (&ws);
521  FD_ZERO (&es);
522  max_fd = MHD_INVALID_SOCKET;
523  result = urh_to_fdset (urh,
524  &rs,
525  &ws,
526  &es,
527  &max_fd,
528  FD_SETSIZE);
529  if (! result)
530  {
531 #ifdef HAVE_MESSAGES
532  MHD_DLOG (con->daemon,
533  MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
534  _ ("Error preparing select.\n"));
535 #endif
536  break;
537  }
538  /* FIXME: does this check really needed? */
539  if (MHD_INVALID_SOCKET != max_fd)
540  {
541  struct timeval*tvp;
542  struct timeval tv;
543  if ( (con->tls_read_ready) &&
544  (urh->in_buffer_used < urh->in_buffer_size))
545  { /* No need to wait if incoming data is already pending in TLS buffers. */
546  tv.tv_sec = 0;
547  tv.tv_usec = 0;
548  tvp = &tv;
549  }
550  else
551  tvp = NULL;
552  num_ready = MHD_SYS_select_ (max_fd + 1,
553  &rs,
554  &ws,
555  &es,
556  tvp);
557  }
558  else
559  num_ready = 0;
560  if (num_ready < 0)
561  {
562  const int err = MHD_socket_get_error_ ();
563 
564  if (MHD_SCKT_ERR_IS_EINTR_ (err))
565  continue;
566 #ifdef HAVE_MESSAGES
567  MHD_DLOG (con->daemon,
568  MHD_SC_UNEXPECTED_SELECT_ERROR,
569  _ ("Error during select (%d): `%s'\n"),
570  err,
571  MHD_socket_strerr_ (err));
572 #endif
573  break;
574  }
575  urh_from_fdset (urh,
576  &rs,
577  &ws,
578  &es);
579  MHD_upgrade_response_handle_process_ (urh);
580  }
581 }
582 
583 
584 #endif
585 
586 
609 enum MHD_StatusCode
610 MHD_daemon_run_from_select (struct MHD_Daemon *daemon,
611  const fd_set *read_fd_set,
612 
613 
614  const fd_set *write_fd_set,
615  const fd_set *except_fd_set)
616 {
617  if ( (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) ||
618  (MHD_ELS_POLL == daemon->event_loop_syscall) )
619  return MHD_SC_CONFIGURATION_MISSMATCH_FOR_RUN_SELECT;
620  if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
621  {
622 #ifdef EPOLL_SUPPORT
623  enum MHD_StatusCode sc;
624 
625  sc = MHD_daemon_epoll_ (daemon,
626  MHD_NO);
627  MHD_connection_cleanup_ (daemon);
628  return sc;
629 #else /* ! EPOLL_SUPPORT */
630  return MHD_NO;
631 #endif /* ! EPOLL_SUPPORT */
632  }
633 
634  /* Resuming external connections when using an extern mainloop */
635  if (! daemon->disallow_suspend_resume)
636  (void) MHD_resume_suspended_connections_ (daemon);
637 
638  return internal_run_from_select (daemon,
639  read_fd_set,
640  write_fd_set,
641  except_fd_set);
642 }
643 
644 
653 enum MHD_StatusCode
654 MHD_daemon_select_ (struct MHD_Daemon *daemon,
655  int may_block)
656 {
657  int num_ready;
658  fd_set rs;
659  fd_set ws;
660  fd_set es;
661  MHD_socket maxsock;
662  struct timeval timeout;
663  struct timeval *tv;
664  MHD_UNSIGNED_LONG_LONG ltimeout;
665  MHD_socket ls;
666  enum MHD_StatusCode sc;
667  enum MHD_StatusCode sc2;
668 
669  timeout.tv_sec = 0;
670  timeout.tv_usec = 0;
671  if (daemon->shutdown)
672  return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
673  FD_ZERO (&rs);
674  FD_ZERO (&ws);
675  FD_ZERO (&es);
676  maxsock = MHD_INVALID_SOCKET;
677  sc = MHD_SC_OK;
678  if ( (! daemon->disallow_suspend_resume) &&
680  (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) )
681  may_block = MHD_NO;
682 
683  if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
684  {
685 
686  /* single-threaded, go over everything */
687  if (MHD_SC_OK !=
688  (sc = internal_get_fdset2 (daemon,
689  &rs,
690  &ws,
691  &es,
692  &maxsock,
693  FD_SETSIZE)))
694  {
695 #ifdef HAVE_MESSAGES
696  MHD_DLOG (daemon,
697  sc,
698  _ ("Could not obtain daemon fdsets.\n"));
699 #endif
700  }
701  }
702  else
703  {
704  /* accept only, have one thread per connection */
705  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
706  (! daemon->was_quiesced) &&
707  (! MHD_add_to_fd_set_ (ls,
708  &rs,
709  &maxsock,
710  FD_SETSIZE)) )
711  {
712 #ifdef HAVE_MESSAGES
713  MHD_DLOG (daemon,
714  MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
715  _ ("Could not add listen socket to fdset.\n"));
716 #endif
717  return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
718  }
719  }
720  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
721  (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
722  &rs,
723  &maxsock,
724  FD_SETSIZE)) )
725  {
726 #if defined(MHD_WINSOCK_SOCKETS)
727  /* fdset limit reached, new connections
728  cannot be handled. Remove listen socket FD
729  from fdset and retry to add ITC FD. */
730  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
731  (! daemon->was_quiesced) )
732  {
733  FD_CLR (ls,
734  &rs);
735  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
736  &rs,
737  &maxsock,
738  FD_SETSIZE))
739  {
740 #endif /* MHD_WINSOCK_SOCKETS */
741  sc = MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
742 #ifdef HAVE_MESSAGES
743  MHD_DLOG (daemon,
744  sc,
745  _ (
746  "Could not add control inter-thread communication channel FD to fdset.\n"));
747 #endif
748 #if defined(MHD_WINSOCK_SOCKETS)
749  }
750 }
751 
752 
753 #endif /* MHD_WINSOCK_SOCKETS */
754  }
755  /* Stop listening if we are at the configured connection limit */
756  /* If we're at the connection limit, no point in really
757  accepting new connections; however, make sure we do not miss
758  the shutdown OR the termination of an existing connection; so
759  only do this optimization if we have a signaling ITC in
760  place. */
761  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
762  (MHD_ITC_IS_VALID_ (daemon->itc)) &&
763  ( (daemon->connections == daemon->global_connection_limit) ||
764  (daemon->at_limit) ) )
765  {
766  FD_CLR (ls,
767  &rs);
768  }
769  tv = NULL;
770  if (MHD_SC_OK != sc)
771  may_block = MHD_NO;
772  if (MHD_NO == may_block)
773  {
774  timeout.tv_usec = 0;
775  timeout.tv_sec = 0;
776  tv = &timeout;
777  }
778  else if ( (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) &&
779  (MHD_SC_OK ==
780  MHD_daemon_get_timeout (daemon,
781  &ltimeout)) )
782  {
783  /* ltimeout is in ms */
784  timeout.tv_usec = (ltimeout % 1000) * 1000;
785  if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
786  timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
787  else
788  timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
789  tv = &timeout;
790  }
791  num_ready = MHD_SYS_select_ (maxsock + 1,
792  &rs,
793  &ws,
794  &es,
795  tv);
796  if (daemon->shutdown)
797  return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
798  if (num_ready < 0)
799  {
800  const int err = MHD_socket_get_error_ ();
801 
802  if (MHD_SCKT_ERR_IS_EINTR_ (err))
803  return sc;
804 #ifdef HAVE_MESSAGES
805  MHD_DLOG (daemon,
806  MHD_SC_UNEXPECTED_SELECT_ERROR,
807  _ ("select failed: %s\n"),
808  MHD_socket_strerr_ (err));
809 #endif
810  return MHD_SC_UNEXPECTED_SELECT_ERROR;
811  }
812  if (MHD_SC_OK !=
813  (sc2 = internal_run_from_select (daemon,
814  &rs,
815  &ws,
816  &es)))
817  return sc2;
818  return sc;
819 }
820 
821 /* end of daemon_select.c */
enum MHD_StatusCode MHD_accept_connection_(struct MHD_Daemon *daemon)
functions to add connection to our active set
int MHD_connection_call_handlers_(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
function to call event handlers based on event mask
void MHD_connection_cleanup_(struct MHD_Daemon *daemon)
functions to cleanup completed connection
complete upgrade socket forwarding operation in TLS mode
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
non-public functions provided by daemon_epoll.c
enum MHD_StatusCode MHD_daemon_select_(struct MHD_Daemon *daemon, int may_block)
non-public functions provided by daemon_select.c
enum MHD_StatusCode MHD_daemon_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
static enum MHD_StatusCode internal_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
enum MHD_StatusCode MHD_daemon_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
enum MHD_StatusCode MHD_daemon_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
enum MHD_StatusCode MHD_daemon_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
Definition: daemon_select.c:68
static enum MHD_StatusCode internal_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
@ MHD_EPOLL_STATE_READ_READY
Definition: internal.h:600
@ MHD_EPOLL_STATE_WRITE_READY
Definition: internal.h:606
@ MHD_EPOLL_STATE_ERROR
Definition: internal.h:626
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:140
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: mhd_sockets.c:377
#define _MHD_SYS_DEFAULT_FD_SETSIZE
Definition: mhd_sockets.h:126
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:542
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:634
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:336
#define NULL
Definition: reason_phrase.c:30
#define _(String)
Definition: mhd_options.h:42
internal shared structures
@ MHD_EVENT_LOOP_INFO_READ
Definition: internal.h:234
@ MHD_EVENT_LOOP_INFO_WRITE
Definition: internal.h:239
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition: internal.h:249
@ MHD_EVENT_LOOP_INFO_BLOCK
Definition: internal.h:244
int MHD_socket
Definition: microhttpd.h:196
@ MHD_NO
Definition: microhttpd.h:146
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:299
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:197
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
void MHD_request_resume(struct MHD_Request *request)
bool MHD_resume_suspended_connections_(struct MHD_Daemon *daemon)
implementation of MHD_request_resume()
MHD_socket socket_fd
Definition: internal.h:752
bool tls_read_ready
Definition: internal.h:769
struct MHD_Request request
Definition: internal.h:717
struct MHD_Connection * prev
Definition: internal.h:656
struct MHD_Daemon * daemon
Definition: internal.h:675
bool data_already_pending
Definition: internal.h:1500
bool at_limit
Definition: internal.h:1483
bool was_quiesced
Definition: internal.h:1505
unsigned int connections
Definition: internal.h:1361
struct MHD_itc_ itc
Definition: internal.h:1410
enum MHD_EventLoopSyscall event_loop_syscall
Definition: internal.h:1436
volatile bool shutdown
Definition: internal.h:1526
bool disallow_suspend_resume
Definition: internal.h:1468
MHD_socket listen_socket
Definition: internal.h:1377
enum MHD_ThreadingMode threading_mode
Definition: internal.h:1417
unsigned int global_connection_limit
Definition: internal.h:1351
struct MHD_Connection * connections_tail
Definition: internal.h:1160
enum MHD_RequestEventLoopInfo event_loop_info
Definition: internal.h:559
function to process upgrade activity (over TLS)