GNU libmicrohttpd  0.9.65
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  {
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 | MHD_POLL_REVENTS_ERR_DISC))))
393  goto exit;
394  }
395 #endif
396 #ifdef UPGRADE_SUPPORT
397  if (MHD_REQUEST_UPGRADE == con->request.state)
398  {
399  /* Normal HTTP processing is finished,
400  * notify application. */
401  if (NULL != con->request.response->termination_cb)
405  con->request.client_context);
406  thread_main_connection_upgrade (con);
407  /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
408 
409  /* "Upgraded" data will not be used in this thread from this point. */
410  con->request.urh->clean_ready = true;
411  /* If 'urh->was_closed' set to true, connection will be
412  * moved immediately to cleanup list. Otherwise connection
413  * will stay in suspended list until 'urh' will be marked
414  * with 'was_closed' by application. */
415  MHD_request_resume (&con->request);
416 
417  /* skip usual clean up */
418  return (MHD_THRD_RTRN_TYPE_) 0;
419  }
420 #endif /* UPGRADE_SUPPORT */
421  }
422 #if DEBUG_CLOSE
423 #ifdef HAVE_MESSAGES
424  MHD_DLOG (con->daemon,
425  MHD_SC_THREAD_TERMINATING,
426  _("Processing thread terminating. Closing connection\n"));
427 #endif
428 #endif
429  if (MHD_REQUEST_CLOSED != con->request.state)
431  (daemon->shutdown) ?
435 exit:
436  if (NULL != con->request.response)
437  {
439  con->request.response = NULL;
440  }
441 
442  if (MHD_INVALID_SOCKET != con->socket_fd)
443  {
444  shutdown (con->socket_fd,
445  SHUT_WR);
446  /* 'socket_fd' can be used in other thread to signal shutdown.
447  * To avoid data races, do not close socket here. Daemon will
448  * use more connections only after cleanup anyway. */
449  }
450  return (MHD_THRD_RTRN_TYPE_) 0;
451 }
452 
453 
463 static ssize_t
464 recv_param_adapter (struct MHD_Connection *connection,
465  void *other,
466  size_t i)
467 {
468  ssize_t ret;
469 
470  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
471  (MHD_REQUEST_CLOSED == connection->request.state) )
472  {
473  return MHD_ERR_NOTCONN_;
474  }
475  if (i > MHD_SCKT_SEND_MAX_SIZE_)
476  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
477 
478  ret = MHD_recv_ (connection->socket_fd,
479  other,
480  i);
481  if (0 > ret)
482  {
483  const int err = MHD_socket_get_error_ ();
484  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
485  {
486 #ifdef EPOLL_SUPPORT
487  /* Got EAGAIN --- no longer read-ready */
488  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
489 #endif /* EPOLL_SUPPORT */
490  return MHD_ERR_AGAIN_;
491  }
492  if (MHD_SCKT_ERR_IS_EINTR_ (err))
493  return MHD_ERR_AGAIN_;
495  return MHD_ERR_CONNRESET_;
496  /* Treat any other error as hard error. */
497  return MHD_ERR_NOTCONN_;
498  }
499 #ifdef EPOLL_SUPPORT
500  else if (i > (size_t)ret)
501  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
502 #endif /* EPOLL_SUPPORT */
503  return ret;
504 }
505 
506 
516 static ssize_t
517 send_param_adapter (struct MHD_Connection *connection,
518  const void *other,
519  size_t i)
520 {
521  ssize_t ret;
522 
523  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
524  (MHD_REQUEST_CLOSED == connection->request.state) )
525  {
526  return MHD_ERR_NOTCONN_;
527  }
528  if (i > MHD_SCKT_SEND_MAX_SIZE_)
529  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
530 
531  ret = MHD_send_ (connection->socket_fd,
532  other,
533  i);
534  if (0 > ret)
535  {
536  const int err = MHD_socket_get_error_();
537 
538  if (MHD_SCKT_ERR_IS_EAGAIN_(err))
539  {
540 #ifdef EPOLL_SUPPORT
541  /* EAGAIN --- no longer write-ready */
542  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
543 #endif /* EPOLL_SUPPORT */
544  return MHD_ERR_AGAIN_;
545  }
546  if (MHD_SCKT_ERR_IS_EINTR_ (err))
547  return MHD_ERR_AGAIN_;
549  return MHD_ERR_CONNRESET_;
550  /* Treat any other error as hard error. */
551  return MHD_ERR_NOTCONN_;
552  }
553 #ifdef EPOLL_SUPPORT
554  else if (i > (size_t)ret)
555  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
556 #endif /* EPOLL_SUPPORT */
557  return ret;
558 }
559 
560 
583 static enum MHD_StatusCode
585  MHD_socket client_socket,
586  const struct sockaddr *addr,
587  socklen_t addrlen,
588  bool external_add,
589  bool non_blck)
590 {
591  enum MHD_StatusCode sc;
592  struct MHD_Connection *connection;
593  int eno = 0;
594 
595  /* Direct add to master daemon could happen only with "external" add mode. */
596  mhd_assert ( (NULL == daemon->worker_pool) ||
597  (external_add) );
598  if ( (external_add) &&
599  (NULL != daemon->worker_pool) )
600  {
601  unsigned int i;
602 
603  /* have a pool, try to find a pool with capacity; we use the
604  socket as the initial offset into the pool for load
605  balancing */
606  for (i = 0; i < daemon->worker_pool_size; ++i)
607  {
608  struct MHD_Daemon * const worker =
609  &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
610  if (worker->connections < worker->global_connection_limit)
611  return internal_add_connection (worker,
612  client_socket,
613  addr,
614  addrlen,
615  true,
616  non_blck);
617  }
618  /* all pools are at their connection limit, must refuse */
619  MHD_socket_close_chk_ (client_socket);
620 #if ENFILE
621  errno = ENFILE;
622 #endif
623  return MHD_SC_LIMIT_CONNECTIONS_REACHED;
624  }
625 
626  if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
627  NULL)) &&
628  (MHD_ELS_SELECT == daemon->event_loop_syscall) )
629  {
630 #ifdef HAVE_MESSAGES
631  MHD_DLOG (daemon,
632  MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
633  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
634  (int) client_socket,
635  (int) FD_SETSIZE);
636 #endif
637  MHD_socket_close_chk_ (client_socket);
638 #if EINVAL
639  errno = EINVAL;
640 #endif
641  return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
642  }
643 
644 #ifdef MHD_socket_nosignal_
645  if (! MHD_socket_nosignal_ (client_socket))
646  {
647 #ifdef HAVE_MESSAGES
648  MHD_DLOG (daemon,
649  MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED,
650  _("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
652 #endif
653 #ifndef MSG_NOSIGNAL
654  /* Cannot use socket as it can produce SIGPIPE. */
655 #ifdef ENOTSOCK
656  errno = ENOTSOCK;
657 #endif /* ENOTSOCK */
658  return MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED;
659 #endif /* ! MSG_NOSIGNAL */
660  }
661 #endif /* MHD_socket_nosignal_ */
662 
663 
664 #ifdef HAVE_MESSAGES
665 #if DEBUG_CONNECT
666  MHD_DLOG (daemon,
667  MHD_SC_CONNECTION_ACCEPTED,
668  _("Accepted connection on socket %d\n"),
669  client_socket);
670 #endif
671 #endif
672  if ( (daemon->connections == daemon->global_connection_limit) ||
673  (MHD_NO == MHD_ip_limit_add (daemon,
674  addr,
675  addrlen)) )
676  {
677  /* above connection limit - reject */
678 #ifdef HAVE_MESSAGES
679  MHD_DLOG (daemon,
680  MHD_SC_LIMIT_CONNECTIONS_REACHED,
681  _("Server reached connection limit. Closing inbound connection.\n"));
682 #endif
683  MHD_socket_close_chk_ (client_socket);
684 #if ENFILE
685  errno = ENFILE;
686 #endif
687  return MHD_SC_LIMIT_CONNECTIONS_REACHED;
688  }
689 
690  /* apply connection acceptance policy if present */
691  if ( (NULL != daemon->accept_policy_cb) &&
692  (MHD_NO ==
693  daemon->accept_policy_cb (daemon->accept_policy_cb_cls,
694  addr,
695  addrlen)) )
696  {
697 #if DEBUG_CLOSE
698 #ifdef HAVE_MESSAGES
699  MHD_DLOG (daemon,
700  MHD_SC_ACCEPT_POLICY_REJECTED,
701  _("Connection rejected by application. Closing connection.\n"));
702 #endif
703 #endif
704  MHD_socket_close_chk_ (client_socket);
705  MHD_ip_limit_del (daemon,
706  addr,
707  addrlen);
708 #if EACCESS
709  errno = EACCESS;
710 #endif
711  return MHD_SC_ACCEPT_POLICY_REJECTED;
712  }
713 
714  if (NULL ==
715  (connection = MHD_calloc_ (1,
716  sizeof (struct MHD_Connection))))
717  {
718  eno = errno;
719 #ifdef HAVE_MESSAGES
720  MHD_DLOG (daemon,
721  MHD_SC_CONNECTION_MALLOC_FAILURE,
722  "Error allocating memory: %s\n",
723  MHD_strerror_ (errno));
724 #endif
725  MHD_socket_close_chk_ (client_socket);
726  MHD_ip_limit_del (daemon,
727  addr,
728  addrlen);
729  errno = eno;
730  return MHD_SC_CONNECTION_MALLOC_FAILURE;
731  }
732  connection->pool
734  if (NULL == connection->pool)
735  {
736 #ifdef HAVE_MESSAGES
737  MHD_DLOG (daemon,
738  MHD_SC_POOL_MALLOC_FAILURE,
739  _("Error allocating memory: %s\n"),
740  MHD_strerror_ (errno));
741 #endif
742  MHD_socket_close_chk_ (client_socket);
743  MHD_ip_limit_del (daemon,
744  addr,
745  addrlen);
746  free (connection);
747 #if ENOMEM
748  errno = ENOMEM;
749 #endif
750  return MHD_SC_POOL_MALLOC_FAILURE;
751  }
752 
753  connection->connection_timeout = daemon->connection_default_timeout;
754  memcpy (&connection->addr,
755  addr,
756  addrlen);
757  connection->addr_len = addrlen;
758  connection->socket_fd = client_socket;
759  connection->sk_nonblck = non_blck;
760  connection->daemon = daemon;
762 
763 #ifdef HTTPS_SUPPORT
764  if (NULL != daemon->tls_api)
765  {
766  connection->tls_cs
767  = daemon->tls_api->setup_connection (daemon->tls_api->cls,
768  NULL /* FIXME */);
769  if (NULL == connection->tls_cs)
770  {
771  eno = EINVAL;
772  sc = -1; // FIXME!
773  goto cleanup;
774  }
775  }
776  else
777 #endif /* ! HTTPS_SUPPORT */
778  {
779  /* set default connection handlers */
780  connection->recv_cls = &recv_param_adapter;
781  connection->send_cls = &send_param_adapter;
782  }
784  /* Firm check under lock. */
785  if (daemon->connections >= daemon->global_connection_limit)
786  {
788  /* above connection limit - reject */
789 #ifdef HAVE_MESSAGES
790  MHD_DLOG (daemon,
791  MHD_SC_LIMIT_CONNECTIONS_REACHED,
792  _("Server reached connection limit. Closing inbound connection.\n"));
793 #endif
794 #if ENFILE
795  eno = ENFILE;
796 #endif
797  sc = MHD_SC_LIMIT_CONNECTIONS_REACHED;
798  goto cleanup;
799  }
800  daemon->connections++;
801  if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
802  {
804  daemon->normal_timeout_tail,
805  connection);
806  }
807  DLL_insert (daemon->connections_head,
808  daemon->connections_tail,
809  connection);
811 
812  if (NULL != daemon->notify_connection_cb)
814  connection,
816 
817  /* attempt to create handler thread */
818  if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
819  {
820  if (! MHD_create_named_thread_ (&connection->pid,
821  "MHD-connection",
822  daemon->thread_stack_limit_b,
824  connection))
825  {
826  eno = errno;
827 #ifdef HAVE_MESSAGES
828  MHD_DLOG (daemon,
829  MHD_SC_THREAD_LAUNCH_FAILURE,
830  "Failed to create a thread: %s\n",
831  MHD_strerror_ (eno));
832 #endif
833  sc = MHD_SC_THREAD_LAUNCH_FAILURE;
834  goto cleanup;
835  }
836  }
837  else
838  {
839  connection->pid = daemon->pid;
840  }
841 #ifdef EPOLL_SUPPORT
842  if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
843  {
844  if ( (! daemon->enable_turbo) ||
845  (external_add))
846  { /* Do not manipulate EReady DL-list in 'external_add' mode. */
847  struct epoll_event event;
848 
849  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
850  event.data.ptr = connection;
851  if (0 != epoll_ctl (daemon->epoll_fd,
852  EPOLL_CTL_ADD,
853  client_socket,
854  &event))
855  {
856  eno = errno;
857 #ifdef HAVE_MESSAGES
858  MHD_DLOG (daemon,
859  MHD_SC_EPOLL_CTL_ADD_FAILED,
860  _("Call to epoll_ctl failed: %s\n"),
862 #endif
863  sc = MHD_SC_EPOLL_CTL_ADD_FAILED;
864  goto cleanup;
865  }
866  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
867  }
868  else
869  {
870  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
872  EDLL_insert (daemon->eready_head,
873  daemon->eready_tail,
874  connection);
875  }
876  }
877  else /* This 'else' is combined with next 'if'. */
878 #endif
879  if ( (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) &&
880  (external_add) &&
881  (MHD_ITC_IS_VALID_(daemon->itc)) &&
882  (! MHD_itc_activate_ (daemon->itc,
883  "n")) )
884  {
885 #ifdef HAVE_MESSAGES
886  MHD_DLOG (daemon,
887  MHD_SC_ITC_USE_FAILED,
888  _("Failed to signal new connection via inter-thread communication channel (not necessarily fatal, continuing anyway)."));
889 #endif
890  }
891  return MHD_SC_OK;
892 
893  cleanup:
894  if (NULL != daemon->notify_connection_cb)
896  connection,
898 #ifdef HTTPS_SUPPORT
899  if ( (NULL != daemon->tls_api) &&
900  (NULL != connection->tls_cs) )
901  daemon->tls_api->teardown_connection (daemon->tls_api->cls,
902  connection->tls_cs);
903 #endif /* HTTPS_SUPPORT */
904  MHD_socket_close_chk_ (client_socket);
905  MHD_ip_limit_del (daemon,
906  addr,
907  addrlen);
909  if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
910  {
912  daemon->normal_timeout_tail,
913  connection);
914  }
915  DLL_remove (daemon->connections_head,
916  daemon->connections_tail,
917  connection);
919  MHD_pool_destroy (connection->pool);
920  free (connection);
921  if (0 != eno)
922  errno = eno;
923  else
924  errno = EINVAL;
925  return sc;
926 }
927 
928 
955 enum MHD_StatusCode
957  MHD_socket client_socket,
958  const struct sockaddr *addr,
959  socklen_t addrlen)
960 {
961  bool sk_nonbl;
962 
963  if (! MHD_socket_nonblocking_ (client_socket))
964  {
965 #ifdef HAVE_MESSAGES
966  MHD_DLOG (daemon,
967  MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
968  _("Failed to set nonblocking mode on new client socket: %s\n"),
970 #endif
971  sk_nonbl = false;
972  }
973  else
974  {
975  sk_nonbl = true;
976  }
977 
978  if ( (daemon->enable_turbo) &&
979  (! MHD_socket_noninheritable_ (client_socket)) )
980  {
981 #ifdef HAVE_MESSAGES
982  MHD_DLOG (daemon,
983  MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
984  _("Failed to set noninheritable mode on new client socket.\n"));
985 #endif
986  }
987  return internal_add_connection (daemon,
988  client_socket,
989  addr,
990  addrlen,
991  true,
992  sk_nonbl);
993 }
994 
995 
1005 enum MHD_StatusCode
1007 {
1008  struct sockaddr_storage addrstorage;
1009  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
1010  socklen_t addrlen;
1011  MHD_socket s;
1012  MHD_socket fd;
1013  bool sk_nonbl;
1014 
1015  addrlen = sizeof (addrstorage);
1016  memset (addr,
1017  0,
1018  sizeof (addrstorage));
1019  if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_socket)) ||
1020  (daemon->was_quiesced) )
1021  return MHD_SC_DAEMON_ALREADY_QUIESCED;
1022 #ifdef USE_ACCEPT4
1023  s = accept4 (fd,
1024  addr,
1025  &addrlen,
1027  sk_nonbl = (0 != MAYBE_SOCK_NONBLOCK);
1028 #else /* ! USE_ACCEPT4 */
1029  s = accept (fd,
1030  addr,
1031  &addrlen);
1032  sk_nonbl = false;
1033 #endif /* ! USE_ACCEPT4 */
1034  if ( (MHD_INVALID_SOCKET == s) ||
1035  (addrlen <= 0) )
1036  {
1037  const int err = MHD_socket_get_error_ ();
1038 
1039  /* This could be a common occurance with multiple worker threads */
1040  if (MHD_SCKT_ERR_IS_ (err,
1042  return MHD_SC_DAEMON_ALREADY_SHUTDOWN; /* can happen during shutdown, let's hope this is the cause... */
1044  return MHD_SC_ACCEPT_FAST_DISCONNECT; /* do not print error if client just disconnected early */
1045  if (MHD_SCKT_ERR_IS_EAGAIN_ (err) )
1046  return MHD_SC_ACCEPT_FAILED_EAGAIN;
1047  if (MHD_INVALID_SOCKET != s)
1048  {
1050  }
1051  if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
1052  {
1053  /* system/process out of resources */
1054  if (0 == daemon->connections)
1055  {
1056 #ifdef HAVE_MESSAGES
1057  /* Not setting 'at_limit' flag, as there is no way it
1058  would ever be cleared. Instead trying to produce
1059  bit fat ugly warning. */
1060  MHD_DLOG (daemon,
1061  MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY,
1062  _("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"));
1063 #endif
1064  return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY;
1065  }
1066  else
1067  {
1069  daemon->at_limit = true;
1071 #ifdef HAVE_MESSAGES
1072  MHD_DLOG (daemon,
1073  MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED,
1074  _("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
1075  (unsigned int) daemon->connections);
1076 #endif
1077  return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED;
1078  }
1079  }
1080 #ifdef HAVE_MESSAGES
1081  MHD_DLOG (daemon,
1082  MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY,
1083  _("Error accepting connection: %s\n"),
1084  MHD_socket_strerr_(err));
1085 #endif
1086  return MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY;
1087  }
1088 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
1089  if (! MHD_socket_nonblocking_ (s))
1090  {
1091 #ifdef HAVE_MESSAGES
1092  MHD_DLOG (daemon,
1093  MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
1094  _("Failed to set nonblocking mode on incoming connection socket: %s\n"),
1096 #endif
1097  }
1098  else
1099  sk_nonbl = true;
1100 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
1101 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
1102  if (! MHD_socket_noninheritable_ (s))
1103  {
1104 #ifdef HAVE_MESSAGES
1105  MHD_DLOG (daemon,
1106  MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
1107  _("Failed to set noninheritable mode on incoming connection socket.\n"));
1108 #endif
1109  }
1110 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
1111 #ifdef HAVE_MESSAGES
1112 #if DEBUG_CONNECT
1113  MHD_DLOG (daemon,
1114  MHD_SC_CONNECTION_ACCEPTED,
1115  _("Accepted connection on socket %d\n"),
1116  s);
1117 #endif
1118 #endif
1119  return internal_add_connection (daemon,
1120  s,
1121  addr,
1122  addrlen,
1123  false,
1124  sk_nonbl);
1125 }
1126 
1127 /* end of connection_add.c */
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
struct MHD_Request request
Definition: internal.h:714
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:1433
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:1278
socklen_t addr_len
Definition: internal.h:730
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:323
struct sockaddr_storage addr
Definition: internal.h:725
void * data
Definition: microhttpd.h:2948
non-public functions provided by daemon_select.c
MHD_thread_handle_ID_ pid
Definition: internal.h:1246
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
unsigned int global_connection_limit
Definition: internal.h:1348
MHD_AcceptPolicyCallback accept_policy_cb
Definition: internal.h:1023
void * termination_cb_cls
Definition: internal.h:1614
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
size_t thread_stack_limit_b
Definition: internal.h:1299
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:96
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:525
#define EDLL_insert(head, tail, element)
Definition: internal.h:1829
MHD_RequestTerminationCallback termination_cb
Definition: internal.h:1609
#define MHD_ERR_AGAIN_
Definition: internal.h:1864
#define EXTRA_SLOTS
MHD_thread_handle_ID_ pid
Definition: internal.h:720
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:374
int MHD_socket
Definition: microhttpd.h:187
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
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:603
internal shared structures
#define MHD_ERR_CONNRESET_
Definition: internal.h:1869
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
MHD_socket listen_socket
Definition: internal.h:1374
struct MHD_Daemon * daemon
Definition: internal.h:672
MHD_NotifyConnectionCallback notify_connection_cb
Definition: internal.h:1044
function to update last activity of a connection
time_t connection_default_timeout
Definition: internal.h:1368
enum MHD_REQUEST_STATE state
Definition: internal.h:546
#define DLL_insert(head, tail, element)
Definition: internal.h:1742
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
bool was_quiesced
Definition: internal.h:1502
struct MHD_Connection * connections_tail
Definition: internal.h:1157
struct MHD_Daemon * worker_pool
Definition: internal.h:1070
int fd
Definition: microhttpd.h:3076
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:749
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:220
unsigned int worker_pool_size
Definition: internal.h:1363
struct MHD_Connection * connections_head
Definition: internal.h:1152
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
bool enable_turbo
Definition: internal.h:1487
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:742
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
enum MHD_RequestEventLoopInfo event_loop_info
Definition: internal.h:556
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:1358
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:140
#define DLL_remove(head, tail, element)
Definition: internal.h:1762
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:448
#define MHD_strerror_(errnum)
Definition: mhd_compat.h:44
void * accept_policy_cb_cls
Definition: internal.h:1028
ReceiveCallback recv_cls
Definition: internal.h:703
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1125
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:1806
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:208
bool tls_read_ready
Definition: internal.h:766
struct MHD_itc_ itc
Definition: internal.h:1407
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
time_t last_activity
Definition: internal.h:736
bool sk_nonblck
Definition: internal.h:781
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1132
non-public functions provided by daemon_poll.c
struct MHD_Response * response
Definition: internal.h:380
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:645
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
#define MHD_ERR_NOTCONN_
Definition: internal.h:1875
struct MemoryPool * pool
Definition: internal.h:682
TransmitCallback send_cls
Definition: internal.h:708
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
bool at_limit
Definition: internal.h:1480
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
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:761
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
counting of connections per IP
#define MHD_NO
Definition: microhttpd.h:145
void * notify_connection_cb_cls
Definition: internal.h:1049
enum MHD_ThreadingMode threading_mode
Definition: internal.h:1414
void * client_context
Definition: internal.h:398
volatile bool shutdown
Definition: internal.h:1523
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
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:1262
functions to add connection to our active set
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:633
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:439
#define MAYBE_SOCK_NONBLOCK
Definition: mhd_sockets.h:162
void MHD_response_queue_for_destroy(struct MHD_Response *response)
Definition: response.c:88
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:156
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:398