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