GNU libmicrohttpd  0.9.68
connection_add.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 */
24 #include "internal.h"
25 #include "connection_add.h"
27 #include "connection_close.h"
30 #include "daemon_ip_limit.h"
31 #include "daemon_select.h"
32 #include "daemon_poll.h"
33 #include "mhd_sockets.h"
34 
35 
36 #ifdef UPGRADE_SUPPORT
37 
45 static void
46 thread_main_connection_upgrade (struct MHD_Connection *con)
47 {
48 #ifdef HTTPS_SUPPORT
49  struct MHD_Daemon *daemon = con->daemon;
50 
51  /* Here, we need to bi-directionally forward
52  until the application tells us that it is done
53  with the socket; */
54  if ( (NULL != daemon->tls_api) &&
55  (MHD_ELS_POLL != daemon->event_loop_syscall) )
56  {
57  MHD_daemon_upgrade_connection_with_select_ (con);
58  }
59 #ifdef HAVE_POLL
60  else if (NULL != daemon->tls_api)
61  {
62  MHD_daemon_upgrade_connection_with_poll_ (con);
63  }
64 #endif
65  /* end HTTPS */
66 #endif /* HTTPS_SUPPORT */
67  /* TLS forwarding was finished. Cleanup socketpair. */
69  /* Do not set 'urh->clean_ready' yet as 'urh' will be used
70  * in connection thread for a little while. */
71 }
72 #endif /* UPGRADE_SUPPORT */
73 
74 
82 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
84 {
85  struct MHD_Connection *con = data;
86  struct MHD_Daemon *daemon = con->daemon;
87  int num_ready;
88  fd_set rs;
89  fd_set ws;
90  fd_set es;
91  MHD_socket maxsock;
92  struct timeval tv;
93  struct timeval *tvp;
94  time_t now;
95 #if WINDOWS
96 #ifdef HAVE_POLL
97  int extra_slot;
98 #endif /* HAVE_POLL */
99 #define EXTRA_SLOTS 1
100 #else /* !WINDOWS */
101 #define EXTRA_SLOTS 0
102 #endif /* !WINDOWS */
103 #ifdef HAVE_POLL
104  struct pollfd p[1 + EXTRA_SLOTS];
105 #endif
106 #undef EXTRA_SLOTS
107 #ifdef HAVE_POLL
108  const bool use_poll = (MHD_ELS_POLL == daemon->event_loop_syscall);
109 #else /* ! HAVE_POLL */
110  const bool use_poll = false;
111 #endif /* ! HAVE_POLL */
112  bool was_suspended = false;
113 
114  MHD_thread_init_ (&con->pid);
115 
116  while ( (! daemon->shutdown) &&
117  (MHD_REQUEST_CLOSED != con->request.state) )
118  {
119  const time_t timeout = daemon->connection_default_timeout;
120 #ifdef UPGRADE_SUPPORT
121  struct MHD_UpgradeResponseHandle *const urh = con->request.urh;
122 #else /* ! UPGRADE_SUPPORT */
123  static const void *const urh = NULL;
124 #endif /* ! UPGRADE_SUPPORT */
125 
126  if ( (con->suspended) &&
127  (NULL == urh) )
128  {
129  /* Connection was suspended, wait for resume. */
130  was_suspended = true;
131  if (! use_poll)
132  {
133  FD_ZERO (&rs);
134  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
135  &rs,
136  NULL,
137  FD_SETSIZE))
138  {
139  #ifdef HAVE_MESSAGES
140  MHD_DLOG (con->daemon,
141  MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
142  _ ("Failed to add FD to fd_set\n"));
143  #endif
144  goto exit;
145  }
146  if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
147  &rs,
148  NULL,
149  NULL,
150  NULL))
151  {
152  const int err = MHD_socket_get_error_ ();
153 
154  if (MHD_SCKT_ERR_IS_EINTR_ (err))
155  continue;
156 #ifdef HAVE_MESSAGES
157  MHD_DLOG (con->daemon,
158  MHD_SC_UNEXPECTED_SELECT_ERROR,
159  _ ("Error during select (%d): `%s'\n"),
160  err,
161  MHD_socket_strerr_ (err));
162 #endif
163  break;
164  }
165  }
166 #ifdef HAVE_POLL
167  else /* use_poll */
168  {
169  p[0].events = POLLIN;
170  p[0].fd = MHD_itc_r_fd_ (daemon->itc);
171  p[0].revents = 0;
172  if (0 > MHD_sys_poll_ (p,
173  1,
174  -1))
175  {
177  continue;
178 #ifdef HAVE_MESSAGES
179  MHD_DLOG (con->daemon,
180  MHD_SC_UNEXPECTED_POLL_ERROR,
181  _ ("Error during poll: `%s'\n"),
183 #endif
184  break;
185  }
186  }
187 #endif /* HAVE_POLL */
188  MHD_itc_clear_ (daemon->itc);
189  continue; /* Check again for resume. */
190  } /* End of "suspended" branch. */
191 
192  if (was_suspended)
193  {
194  MHD_connection_update_last_activity_ (con); /* Reset timeout timer. */
195  /* Process response queued during suspend and update states. */
197  was_suspended = false;
198  }
199 
200  tvp = NULL;
201 
203 #ifdef HTTPS_SUPPORT
204  || ( (con->tls_read_ready) &&
206 #endif /* HTTPS_SUPPORT */
207  )
208  {
209  /* do not block: more data may be inside of TLS buffers waiting or
210  * application must provide response data */
211  tv.tv_sec = 0;
212  tv.tv_usec = 0;
213  tvp = &tv;
214  }
215  if ( (NULL == tvp) &&
216  (timeout > 0) )
217  {
218  now = MHD_monotonic_sec_counter ();
219  if (now - con->last_activity > timeout)
220  tv.tv_sec = 0;
221  else
222  {
223  const time_t seconds_left = timeout - (now - con->last_activity);
224 #if ! defined(_WIN32) || defined(__CYGWIN__)
225  tv.tv_sec = seconds_left;
226 #else /* _WIN32 && !__CYGWIN__ */
227  if (seconds_left > TIMEVAL_TV_SEC_MAX)
228  tv.tv_sec = TIMEVAL_TV_SEC_MAX;
229  else
230  tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
231 #endif /* _WIN32 && ! __CYGWIN__ */
232  }
233  tv.tv_usec = 0;
234  tvp = &tv;
235  }
236  if (! use_poll)
237  {
238  /* use select */
239  bool err_state = false;
240 
241  FD_ZERO (&rs);
242  FD_ZERO (&ws);
243  FD_ZERO (&es);
244  maxsock = MHD_INVALID_SOCKET;
245  switch (con->request.event_loop_info)
246  {
248  if (! MHD_add_to_fd_set_ (con->socket_fd,
249  &rs,
250  &maxsock,
251  FD_SETSIZE))
252  err_state = true;
253  break;
255  if (! MHD_add_to_fd_set_ (con->socket_fd,
256  &ws,
257  &maxsock,
258  FD_SETSIZE))
259  err_state = true;
260  break;
262  if (! MHD_add_to_fd_set_ (con->socket_fd,
263  &es,
264  &maxsock,
265  FD_SETSIZE))
266  err_state = true;
267  break;
269  /* how did we get here!? */
270  goto exit;
271  }
272 #if WINDOWS
273  if (MHD_ITC_IS_VALID_ (daemon->itc) )
274  {
275  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
276  &rs,
277  &maxsock,
278  FD_SETSIZE))
279  err_state = 1;
280  }
281 #endif
282  if (err_state)
283  {
284 #ifdef HAVE_MESSAGES
285  MHD_DLOG (con->daemon,
286  MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
287  _ ("Failed to add FD to fd_set\n"));
288 #endif
289  goto exit;
290  }
291 
292  num_ready = MHD_SYS_select_ (maxsock + 1,
293  &rs,
294  &ws,
295  &es,
296  tvp);
297  if (num_ready < 0)
298  {
299  const int err = MHD_socket_get_error_ ();
300 
301  if (MHD_SCKT_ERR_IS_EINTR_ (err))
302  continue;
303 #ifdef HAVE_MESSAGES
304  MHD_DLOG (con->daemon,
305  MHD_SC_UNEXPECTED_SELECT_ERROR,
306  _ ("Error during select (%d): `%s'\n"),
307  err,
308  MHD_socket_strerr_ (err));
309 #endif
310  break;
311  }
312 #if WINDOWS
313  /* Clear ITC before other processing so additional
314  * signals will trigger select() again */
315  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
316  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
317  &rs)) )
318  MHD_itc_clear_ (daemon->itc);
319 #endif
320  if (MHD_NO ==
322  FD_ISSET (con->socket_fd,
323  &rs),
324  FD_ISSET (con->socket_fd,
325  &ws),
326  FD_ISSET (con->socket_fd,
327  &es)) )
328  goto exit;
329  }
330 #ifdef HAVE_POLL
331  else
332  {
333  /* use poll */
334  memset (&p,
335  0,
336  sizeof (p));
337  p[0].fd = con->socket_fd;
338  switch (con->request.event_loop_info)
339  {
341  p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
342  break;
344  p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
345  break;
347  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
348  break;
350  /* how did we get here!? */
351  goto exit;
352  }
353 #if WINDOWS
354  extra_slot = 0;
355  if (MHD_ITC_IS_VALID_ (daemon->itc))
356  {
357  p[1].events |= POLLIN;
358  p[1].fd = MHD_itc_r_fd_ (daemon->itc);
359  p[1].revents = 0;
360  extra_slot = 1;
361  }
362 #endif
363  if (MHD_sys_poll_ (p,
364 #if WINDOWS
365  1 + extra_slot,
366 #else
367  1,
368 #endif
369  (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
370  {
372  continue;
373 #ifdef HAVE_MESSAGES
374  MHD_DLOG (con->daemon,
375  MHD_SC_UNEXPECTED_POLL_ERROR,
376  _ ("Error during poll: `%s'\n"),
378 #endif
379  break;
380  }
381 #if WINDOWS
382  /* Clear ITC before other processing so additional
383  * signals will trigger poll() again */
384  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
385  (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
386  MHD_itc_clear_ (daemon->itc);
387 #endif
388  if (MHD_NO ==
390  (0 != (p[0].revents & POLLIN)),
391  (0 != (p[0].revents & POLLOUT)),
392  (0 != (p[0].revents & (POLLERR
393  |
394  MHD_POLL_REVENTS_ERR_DISC))) ))
395  goto exit;
396  }
397 #endif
398 #ifdef UPGRADE_SUPPORT
399  if (MHD_REQUEST_UPGRADE == con->request.state)
400  {
401  /* Normal HTTP processing is finished,
402  * notify application. */
403  if (NULL != con->request.response->termination_cb)
407  con->request.client_context);
408  thread_main_connection_upgrade (con);
409  /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
410 
411  /* "Upgraded" data will not be used in this thread from this point. */
412  con->request.urh->clean_ready = true;
413  /* If 'urh->was_closed' set to true, connection will be
414  * moved immediately to cleanup list. Otherwise connection
415  * will stay in suspended list until 'urh' will be marked
416  * with 'was_closed' by application. */
417  MHD_request_resume (&con->request);
418 
419  /* skip usual clean up */
420  return (MHD_THRD_RTRN_TYPE_) 0;
421  }
422 #endif /* UPGRADE_SUPPORT */
423  }
424 #if DEBUG_CLOSE
425 #ifdef HAVE_MESSAGES
426  MHD_DLOG (con->daemon,
427  MHD_SC_THREAD_TERMINATING,
428  _ ("Processing thread terminating. Closing connection\n"));
429 #endif
430 #endif
431  if (MHD_REQUEST_CLOSED != con->request.state)
433  (daemon->shutdown) ?
437 exit:
438  if (NULL != con->request.response)
439  {
441  con->request.response = NULL;
442  }
443 
444  if (MHD_INVALID_SOCKET != con->socket_fd)
445  {
446  shutdown (con->socket_fd,
447  SHUT_WR);
448  /* 'socket_fd' can be used in other thread to signal shutdown.
449  * To avoid data races, do not close socket here. Daemon will
450  * use more connections only after cleanup anyway. */
451  }
452  return (MHD_THRD_RTRN_TYPE_) 0;
453 }
454 
455 
465 static ssize_t
466 recv_param_adapter (struct MHD_Connection *connection,
467  void *other,
468  size_t i)
469 {
470  ssize_t ret;
471 
472  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
473  (MHD_REQUEST_CLOSED == connection->request.state) )
474  {
475  return MHD_ERR_NOTCONN_;
476  }
477  if (i > MHD_SCKT_SEND_MAX_SIZE_)
478  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
479 
480  ret = MHD_recv_ (connection->socket_fd,
481  other,
482  i);
483  if (0 > ret)
484  {
485  const int err = MHD_socket_get_error_ ();
486  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
487  {
488 #ifdef EPOLL_SUPPORT
489  /* Got EAGAIN --- no longer read-ready */
490  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
491 #endif /* EPOLL_SUPPORT */
492  return MHD_ERR_AGAIN_;
493  }
494  if (MHD_SCKT_ERR_IS_EINTR_ (err))
495  return MHD_ERR_AGAIN_;
497  return MHD_ERR_CONNRESET_;
498  /* Treat any other error as hard error. */
499  return MHD_ERR_NOTCONN_;
500  }
501 #ifdef EPOLL_SUPPORT
502  else if (i > (size_t) ret)
503  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
504 #endif /* EPOLL_SUPPORT */
505  return ret;
506 }
507 
508 
518 static ssize_t
519 send_param_adapter (struct MHD_Connection *connection,
520  const void *other,
521  size_t i)
522 {
523  ssize_t ret;
524 
525  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
526  (MHD_REQUEST_CLOSED == connection->request.state) )
527  {
528  return MHD_ERR_NOTCONN_;
529  }
530  if (i > MHD_SCKT_SEND_MAX_SIZE_)
531  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
532 
533  ret = MHD_send_ (connection->socket_fd,
534  other,
535  i);
536  if (0 > ret)
537  {
538  const int err = MHD_socket_get_error_ ();
539 
540  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
541  {
542 #ifdef EPOLL_SUPPORT
543  /* EAGAIN --- no longer write-ready */
544  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
545 #endif /* EPOLL_SUPPORT */
546  return MHD_ERR_AGAIN_;
547  }
548  if (MHD_SCKT_ERR_IS_EINTR_ (err))
549  return MHD_ERR_AGAIN_;
551  return MHD_ERR_CONNRESET_;
552  /* Treat any other error as hard error. */
553  return MHD_ERR_NOTCONN_;
554  }
555 #ifdef EPOLL_SUPPORT
556  else if (i > (size_t) ret)
557  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
558 #endif /* EPOLL_SUPPORT */
559  return ret;
560 }
561 
562 
585 static enum MHD_StatusCode
587  MHD_socket client_socket,
588  const struct sockaddr *addr,
589  socklen_t addrlen,
590  bool external_add,
591  bool non_blck)
592 {
593  enum MHD_StatusCode sc;
594  struct MHD_Connection *connection;
595  int eno = 0;
596 
597  /* Direct add to master daemon could happen only with "external" add mode. */
598  mhd_assert ( (NULL == daemon->worker_pool) ||
599  (external_add) );
600  if ( (external_add) &&
601  (NULL != daemon->worker_pool) )
602  {
603  unsigned int i;
604 
605  /* have a pool, try to find a pool with capacity; we use the
606  socket as the initial offset into the pool for load
607  balancing */
608  for (i = 0; i < daemon->worker_pool_size; ++i)
609  {
610  struct MHD_Daemon *const worker =
611  &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
612  if (worker->connections < worker->global_connection_limit)
613  return internal_add_connection (worker,
614  client_socket,
615  addr,
616  addrlen,
617  true,
618  non_blck);
619  }
620  /* all pools are at their connection limit, must refuse */
621  MHD_socket_close_chk_ (client_socket);
622 #if ENFILE
623  errno = ENFILE;
624 #endif
625  return MHD_SC_LIMIT_CONNECTIONS_REACHED;
626  }
627 
628  if ( (! MHD_SCKT_FD_FITS_FDSET_ (client_socket,
629  NULL)) &&
630  (MHD_ELS_SELECT == daemon->event_loop_syscall) )
631  {
632 #ifdef HAVE_MESSAGES
633  MHD_DLOG (daemon,
634  MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
635  _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
636  (int) client_socket,
637  (int) FD_SETSIZE);
638 #endif
639  MHD_socket_close_chk_ (client_socket);
640 #if EINVAL
641  errno = EINVAL;
642 #endif
643  return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
644  }
645 
646 #ifdef MHD_socket_nosignal_
647  if (! MHD_socket_nosignal_ (client_socket))
648  {
649 #ifdef HAVE_MESSAGES
650  MHD_DLOG (daemon,
651  MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED,
652  _ ("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
654 #endif
655 #ifndef MSG_NOSIGNAL
656  /* Cannot use socket as it can produce SIGPIPE. */
657 #ifdef ENOTSOCK
658  errno = ENOTSOCK;
659 #endif /* ENOTSOCK */
660  return MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED;
661 #endif /* ! MSG_NOSIGNAL */
662  }
663 #endif /* MHD_socket_nosignal_ */
664 
665 
666 #ifdef HAVE_MESSAGES
667 #if DEBUG_CONNECT
668  MHD_DLOG (daemon,
669  MHD_SC_CONNECTION_ACCEPTED,
670  _ ("Accepted connection on socket %d\n"),
671  client_socket);
672 #endif
673 #endif
674  if ( (daemon->connections == daemon->global_connection_limit) ||
675  (MHD_NO == MHD_ip_limit_add (daemon,
676  addr,
677  addrlen)) )
678  {
679  /* above connection limit - reject */
680 #ifdef HAVE_MESSAGES
681  MHD_DLOG (daemon,
682  MHD_SC_LIMIT_CONNECTIONS_REACHED,
683  _ (
684  "Server reached connection limit. Closing inbound connection.\n"));
685 #endif
686  MHD_socket_close_chk_ (client_socket);
687 #if ENFILE
688  errno = ENFILE;
689 #endif
690  return MHD_SC_LIMIT_CONNECTIONS_REACHED;
691  }
692 
693  /* apply connection acceptance policy if present */
694  if ( (NULL != daemon->accept_policy_cb) &&
695  (MHD_NO ==
696  daemon->accept_policy_cb (daemon->accept_policy_cb_cls,
697  addr,
698  addrlen)) )
699  {
700 #if DEBUG_CLOSE
701 #ifdef HAVE_MESSAGES
702  MHD_DLOG (daemon,
703  MHD_SC_ACCEPT_POLICY_REJECTED,
704  _ ("Connection rejected by application. Closing connection.\n"));
705 #endif
706 #endif
707  MHD_socket_close_chk_ (client_socket);
708  MHD_ip_limit_del (daemon,
709  addr,
710  addrlen);
711 #if EACCESS
712  errno = EACCESS;
713 #endif
714  return MHD_SC_ACCEPT_POLICY_REJECTED;
715  }
716 
717  if (NULL ==
718  (connection = MHD_calloc_ (1,
719  sizeof (struct MHD_Connection))))
720  {
721  eno = errno;
722 #ifdef HAVE_MESSAGES
723  MHD_DLOG (daemon,
724  MHD_SC_CONNECTION_MALLOC_FAILURE,
725  "Error allocating memory: %s\n",
726  MHD_strerror_ (errno));
727 #endif
728  MHD_socket_close_chk_ (client_socket);
729  MHD_ip_limit_del (daemon,
730  addr,
731  addrlen);
732  errno = eno;
733  return MHD_SC_CONNECTION_MALLOC_FAILURE;
734  }
735  connection->pool
737  if (NULL == connection->pool)
738  {
739 #ifdef HAVE_MESSAGES
740  MHD_DLOG (daemon,
741  MHD_SC_POOL_MALLOC_FAILURE,
742  _ ("Error allocating memory: %s\n"),
743  MHD_strerror_ (errno));
744 #endif
745  MHD_socket_close_chk_ (client_socket);
746  MHD_ip_limit_del (daemon,
747  addr,
748  addrlen);
749  free (connection);
750 #if ENOMEM
751  errno = ENOMEM;
752 #endif
753  return MHD_SC_POOL_MALLOC_FAILURE;
754  }
755 
756  connection->connection_timeout = daemon->connection_default_timeout;
757  memcpy (&connection->addr,
758  addr,
759  addrlen);
760  connection->addr_len = addrlen;
761  connection->socket_fd = client_socket;
762  connection->sk_nonblck = non_blck;
763  connection->daemon = daemon;
764  connection->last_activity = MHD_monotonic_sec_counter ();
765 
766 #ifdef HTTPS_SUPPORT
767  if (NULL != daemon->tls_api)
768  {
769  connection->tls_cs
770  = daemon->tls_api->setup_connection (daemon->tls_api->cls,
771  NULL /* FIXME */);
772  if (NULL == connection->tls_cs)
773  {
774  eno = EINVAL;
775  sc = -1; // FIXME!
776  goto cleanup;
777  }
778  }
779  else
780 #endif /* ! HTTPS_SUPPORT */
781  {
782  /* set default connection handlers */
783  connection->recv_cls = &recv_param_adapter;
784  connection->send_cls = &send_param_adapter;
785  }
787  /* Firm check under lock. */
788  if (daemon->connections >= daemon->global_connection_limit)
789  {
791  /* above connection limit - reject */
792 #ifdef HAVE_MESSAGES
793  MHD_DLOG (daemon,
794  MHD_SC_LIMIT_CONNECTIONS_REACHED,
795  _ (
796  "Server reached connection limit. Closing inbound connection.\n"));
797 #endif
798 #if ENFILE
799  eno = ENFILE;
800 #endif
801  sc = MHD_SC_LIMIT_CONNECTIONS_REACHED;
802  goto cleanup;
803  }
804  daemon->connections++;
805  if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
806  {
808  daemon->normal_timeout_tail,
809  connection);
810  }
811  DLL_insert (daemon->connections_head,
812  daemon->connections_tail,
813  connection);
815 
816  if (NULL != daemon->notify_connection_cb)
818  connection,
820 
821  /* attempt to create handler thread */
822  if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
823  {
824  if (! MHD_create_named_thread_ (&connection->pid,
825  "MHD-connection",
826  daemon->thread_stack_limit_b,
828  connection))
829  {
830  eno = errno;
831 #ifdef HAVE_MESSAGES
832  MHD_DLOG (daemon,
833  MHD_SC_THREAD_LAUNCH_FAILURE,
834  "Failed to create a thread: %s\n",
835  MHD_strerror_ (eno));
836 #endif
837  sc = MHD_SC_THREAD_LAUNCH_FAILURE;
838  goto cleanup;
839  }
840  }
841  else
842  {
843  connection->pid = daemon->pid;
844  }
845 #ifdef EPOLL_SUPPORT
846  if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
847  {
848  if ( (! daemon->enable_turbo) ||
849  (external_add))
850  { /* Do not manipulate EReady DL-list in 'external_add' mode. */
851  struct epoll_event event;
852 
853  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
854  event.data.ptr = connection;
855  if (0 != epoll_ctl (daemon->epoll_fd,
856  EPOLL_CTL_ADD,
857  client_socket,
858  &event))
859  {
860  eno = errno;
861 #ifdef HAVE_MESSAGES
862  MHD_DLOG (daemon,
863  MHD_SC_EPOLL_CTL_ADD_FAILED,
864  _ ("Call to epoll_ctl failed: %s\n"),
866 #endif
867  sc = MHD_SC_EPOLL_CTL_ADD_FAILED;
868  goto cleanup;
869  }
870  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
871  }
872  else
873  {
874  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
877  EDLL_insert (daemon->eready_head,
878  daemon->eready_tail,
879  connection);
880  }
881  }
882  else /* This 'else' is combined with next 'if'. */
883 #endif
884  if ( (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) &&
885  (external_add) &&
886  (MHD_ITC_IS_VALID_ (daemon->itc)) &&
887  (! MHD_itc_activate_ (daemon->itc,
888  "n")) )
889  {
890 #ifdef HAVE_MESSAGES
891  MHD_DLOG (daemon,
892  MHD_SC_ITC_USE_FAILED,
893  _ (
894  "Failed to signal new connection via inter-thread communication channel (not necessarily fatal, continuing anyway)."));
895 #endif
896  }
897  return MHD_SC_OK;
898 
899 cleanup:
900  if (NULL != daemon->notify_connection_cb)
902  connection,
904 #ifdef HTTPS_SUPPORT
905  if ( (NULL != daemon->tls_api) &&
906  (NULL != connection->tls_cs) )
907  daemon->tls_api->teardown_connection (daemon->tls_api->cls,
908  connection->tls_cs);
909 #endif /* HTTPS_SUPPORT */
910  MHD_socket_close_chk_ (client_socket);
911  MHD_ip_limit_del (daemon,
912  addr,
913  addrlen);
915  if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
916  {
918  daemon->normal_timeout_tail,
919  connection);
920  }
921  DLL_remove (daemon->connections_head,
922  daemon->connections_tail,
923  connection);
925  MHD_pool_destroy (connection->pool);
926  free (connection);
927  if (0 != eno)
928  errno = eno;
929  else
930  errno = EINVAL;
931  return sc;
932 }
933 
934 
961 enum MHD_StatusCode
963  MHD_socket client_socket,
964  const struct sockaddr *addr,
965  socklen_t addrlen)
966 {
967  bool sk_nonbl;
968 
969  if (! MHD_socket_nonblocking_ (client_socket))
970  {
971 #ifdef HAVE_MESSAGES
972  MHD_DLOG (daemon,
973  MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
974  _ ("Failed to set nonblocking mode on new client socket: %s\n"),
976 #endif
977  sk_nonbl = false;
978  }
979  else
980  {
981  sk_nonbl = true;
982  }
983 
984  if ( (daemon->enable_turbo) &&
985  (! MHD_socket_noninheritable_ (client_socket)) )
986  {
987 #ifdef HAVE_MESSAGES
988  MHD_DLOG (daemon,
989  MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
990  _ ("Failed to set noninheritable mode on new client socket.\n"));
991 #endif
992  }
993  return internal_add_connection (daemon,
994  client_socket,
995  addr,
996  addrlen,
997  true,
998  sk_nonbl);
999 }
1000 
1001 
1011 enum MHD_StatusCode
1013 {
1014  struct sockaddr_storage addrstorage;
1015  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
1016  socklen_t addrlen;
1017  MHD_socket s;
1018  MHD_socket fd;
1019  bool sk_nonbl;
1020 
1021  addrlen = sizeof (addrstorage);
1022  memset (addr,
1023  0,
1024  sizeof (addrstorage));
1025  if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_socket)) ||
1026  (daemon->was_quiesced) )
1027  return MHD_SC_DAEMON_ALREADY_QUIESCED;
1028 #ifdef USE_ACCEPT4
1029  s = accept4 (fd,
1030  addr,
1031  &addrlen,
1033  sk_nonbl = (0 != MAYBE_SOCK_NONBLOCK);
1034 #else /* ! USE_ACCEPT4 */
1035  s = accept (fd,
1036  addr,
1037  &addrlen);
1038  sk_nonbl = false;
1039 #endif /* ! USE_ACCEPT4 */
1040  if ( (MHD_INVALID_SOCKET == s) ||
1041  (addrlen <= 0) )
1042  {
1043  const int err = MHD_socket_get_error_ ();
1044 
1045  /* This could be a common occurance with multiple worker threads */
1046  if (MHD_SCKT_ERR_IS_ (err,
1048  return MHD_SC_DAEMON_ALREADY_SHUTDOWN; /* can happen during shutdown, let's hope this is the cause... */
1050  return MHD_SC_ACCEPT_FAST_DISCONNECT; /* do not print error if client just disconnected early */
1051  if (MHD_SCKT_ERR_IS_EAGAIN_ (err) )
1052  return MHD_SC_ACCEPT_FAILED_EAGAIN;
1053  if (MHD_INVALID_SOCKET != s)
1054  {
1056  }
1057  if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
1058  {
1059  /* system/process out of resources */
1060  if (0 == daemon->connections)
1061  {
1062 #ifdef HAVE_MESSAGES
1063  /* Not setting 'at_limit' flag, as there is no way it
1064  would ever be cleared. Instead trying to produce
1065  bit fat ugly warning. */
1066  MHD_DLOG (daemon,
1067  MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY,
1068  _ (
1069  "Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
1070 #endif
1071  return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY;
1072  }
1073  else
1074  {
1076  daemon->at_limit = true;
1078 #ifdef HAVE_MESSAGES
1079  MHD_DLOG (daemon,
1080  MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED,
1081  _ (
1082  "Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
1083  (unsigned int) daemon->connections);
1084 #endif
1085  return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED;
1086  }
1087  }
1088 #ifdef HAVE_MESSAGES
1089  MHD_DLOG (daemon,
1090  MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY,
1091  _ ("Error accepting connection: %s\n"),
1092  MHD_socket_strerr_ (err));
1093 #endif
1094  return MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY;
1095  }
1096 #if ! defined(USE_ACCEPT4) || ! defined(HAVE_SOCK_NONBLOCK)
1097  if (! MHD_socket_nonblocking_ (s))
1098  {
1099 #ifdef HAVE_MESSAGES
1100  MHD_DLOG (daemon,
1101  MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
1102  _ (
1103  "Failed to set nonblocking mode on incoming connection socket: %s\n"),
1105 #endif
1106  }
1107  else
1108  sk_nonbl = true;
1109 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
1110 #if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
1111  if (! MHD_socket_noninheritable_ (s))
1112  {
1113 #ifdef HAVE_MESSAGES
1114  MHD_DLOG (daemon,
1115  MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
1116  _ (
1117  "Failed to set noninheritable mode on incoming connection socket.\n"));
1118 #endif
1119  }
1120 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
1121 #ifdef HAVE_MESSAGES
1122 #if DEBUG_CONNECT
1123  MHD_DLOG (daemon,
1124  MHD_SC_CONNECTION_ACCEPTED,
1125  _ ("Accepted connection on socket %d\n"),
1126  s);
1127 #endif
1128 #endif
1129  return internal_add_connection (daemon,
1130  s,
1131  addr,
1132  addrlen,
1133  false,
1134  sk_nonbl);
1135 }
1136 
1137 /* end of connection_add.c */
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:261
struct MHD_Request request
Definition: internal.h:717
int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
enum MHD_EventLoopSyscall event_loop_syscall
Definition: internal.h:1436
void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
size_t connection_memory_limit_b
Definition: internal.h:1281
socklen_t addr_len
Definition: internal.h:733
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:336
struct sockaddr_storage addr
Definition: internal.h:728
void * data
Definition: microhttpd.h:3031
non-public functions provided by daemon_select.c
MHD_thread_handle_ID_ pid
Definition: internal.h:1249
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:180
unsigned int global_connection_limit
Definition: internal.h:1351
MHD_AcceptPolicyCallback accept_policy_cb
Definition: internal.h:1026
void * termination_cb_cls
Definition: internal.h:1617
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
size_t thread_stack_limit_b
Definition: internal.h:1302
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:96
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:541
#define EDLL_insert(head, tail, element)
Definition: internal.h:1832
MHD_RequestTerminationCallback termination_cb
Definition: internal.h:1612
#define MHD_ERR_AGAIN_
Definition: internal.h:1867
#define EXTRA_SLOTS
MHD_thread_handle_ID_ pid
Definition: internal.h:723
time_t MHD_monotonic_sec_counter(void)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: mhd_sockets.c:375
int MHD_socket
Definition: microhttpd.h:187
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:642
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:622
internal shared structures
#define MHD_ERR_CONNRESET_
Definition: internal.h:1872
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
MHD_socket listen_socket
Definition: internal.h:1377
struct MHD_Daemon * daemon
Definition: internal.h:675
MHD_NotifyConnectionCallback notify_connection_cb
Definition: internal.h:1047
function to update last activity of a connection
time_t connection_default_timeout
Definition: internal.h:1371
enum MHD_REQUEST_STATE state
Definition: internal.h:549
#define DLL_insert(head, tail, element)
Definition: internal.h:1745
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:548
bool was_quiesced
Definition: internal.h:1505
struct MHD_Connection * connections_tail
Definition: internal.h:1160
struct MHD_Daemon * worker_pool
Definition: internal.h:1073
int fd
Definition: microhttpd.h:3161
functions to close connection
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:102
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:188
MHD_socket socket_fd
Definition: internal.h:752
enum MHD_StatusCode MHD_daemon_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:222
unsigned int worker_pool_size
Definition: internal.h:1366
struct MHD_Connection * connections_head
Definition: internal.h:1155
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:248
bool enable_turbo
Definition: internal.h:1490
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
complete upgrade socket forwarding operation in TLS mode
time_t connection_timeout
Definition: internal.h:745
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:610
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
enum MHD_RequestEventLoopInfo event_loop_info
Definition: internal.h:559
function to call event handlers based on event mask
enum MHD_StatusCode MHD_accept_connection_(struct MHD_Daemon *daemon)
#define NULL
Definition: reason_phrase.c:30
unsigned int connections
Definition: internal.h:1361
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:140
#define DLL_remove(head, tail, element)
Definition: internal.h:1765
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:464
#define MHD_strerror_(errnum)
Definition: mhd_compat.h:44
void * accept_policy_cb_cls
Definition: internal.h:1031
ReceiveCallback recv_cls
Definition: internal.h:706
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1128
int MHD_connection_call_handlers_(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
void MHD_request_resume(struct MHD_Request *request)
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
#define XDLL_remove(head, tail, element)
Definition: internal.h:1809
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:216
bool tls_read_ready
Definition: internal.h:769
struct MHD_itc_ itc
Definition: internal.h:1410
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
time_t last_activity
Definition: internal.h:739
bool sk_nonblck
Definition: internal.h:784
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
non-public functions provided by daemon_poll.c
struct MHD_Response * response
Definition: internal.h:383
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:674
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:154
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:309
#define MHD_ERR_NOTCONN_
Definition: internal.h:1878
struct MemoryPool * pool
Definition: internal.h:685
TransmitCallback send_cls
Definition: internal.h:711
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:405
bool at_limit
Definition: internal.h:1483
#define XDLL_insert(head, tail, element)
Definition: internal.h:1789
static enum MHD_StatusCode internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck)
#define _(String)
Definition: mhd_options.h:42
bool suspended
Definition: internal.h:764
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:419
counting of connections per IP
#define MHD_NO
Definition: microhttpd.h:145
void * notify_connection_cb_cls
Definition: internal.h:1052
enum MHD_ThreadingMode threading_mode
Definition: internal.h:1417
void * client_context
Definition: internal.h:401
volatile bool shutdown
Definition: internal.h:1526
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:633
void MHD_connection_update_last_activity_(struct MHD_Connection *connection)
bool MHD_request_handle_idle_(struct MHD_Request *request)
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
functions to add connection to our active set
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:655
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:440
#define MAYBE_SOCK_NONBLOCK
Definition: mhd_sockets.h:163
void MHD_response_queue_for_destroy(struct MHD_Response *response)
Definition: response.c:88
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:157
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:414