GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
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
45static void
46thread_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
84static 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) &&
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 {
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)
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. */
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) ?
439exit:
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
467static ssize_t
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 }
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
520static ssize_t
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 }
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
587static enum MHD_StatusCode
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. */
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
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;
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 }
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
901cleanup:
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 }
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
963enum MHD_StatusCode
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
1013enum MHD_StatusCode
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 }
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)
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 */
#define MHD_connection_finish_forward_(conn)
Definition connection.h:165
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_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
@ MHD_CONNECTION_NOTIFY_CLOSED
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
@ MHD_REQUEST_TERMINATED_WITH_ERROR
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)
int MHD_socket_noninheritable_(MHD_socket sock)
int MHD_socket_nonblocking_(MHD_socket sock)
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
#define MHD_SCKT_ERR_IS_(err, code)
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
#define MHD_SCKT_EINTR_
#define MHD_socket_strerr_(err)
#define MHD_socket_last_strerr_()
#define MHD_socket_get_error_()
#define MHD_SCKT_EINVAL_
#define MAYBE_SOCK_NONBLOCK
#define MHD_socket_close_chk_(fd)
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MAYBE_SOCK_CLOEXEC
#define MHD_recv_(s, b, l)
#define MHD_send_(s, b, l)
#define MHD_SCKT_ECONNRESET_
#define MHD_SCKT_LAST_ERR_IS_(code)
#define MHD_SYS_select_(n, r, w, e, t)
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
#define MHD_create_named_thread_(t, n, s, r, a)
#define NULL
#define _(String)
Definition mhd_options.h:42
MHD internal shared structures.
@ MHD_EVENT_LOOP_INFO_READ
Definition internal.h:246
@ MHD_EVENT_LOOP_INFO_WRITE
Definition internal.h:251
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition internal.h:261
@ MHD_EVENT_LOOP_INFO_BLOCK
Definition internal.h:256
int MHD_socket
Definition microhttpd.h:207
@ MHD_NO
Definition microhttpd.h:162
int fd
void * data
#define MHD_INVALID_SOCKET
Definition microhttpd.h:208
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition platform.h:126
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
ReceiveCallback recv_cls
Definition internal.h:706
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