aboutsummaryrefslogtreecommitdiff
path: root/src/lib/connection_add.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/connection_add.c')
-rw-r--r--src/lib/connection_add.c978
1 files changed, 978 insertions, 0 deletions
diff --git a/src/lib/connection_add.c b/src/lib/connection_add.c
new file mode 100644
index 00000000..8d4f12ad
--- /dev/null
+++ b/src/lib/connection_add.c
@@ -0,0 +1,978 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19/**
20 * @file lib/connection_add.c
21 * @brief functions to add connection to our active set
22 * @author Christian Grothoff
23 */
24#include "internal.h"
25#include "connection_add.h"
26#include "daemon_ip_limit.h"
27
28
29/**
30 * Main function of the thread that handles an individual
31 * connection when #MHD_USE_THREAD_PER_CONNECTION is set.
32 *
33 * @param data the `struct MHD_Connection` this thread will handle
34 * @return always 0
35 */
36static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
37thread_main_handle_connection (void *data)
38{
39 struct MHD_Connection *con = data;
40 struct MHD_Daemon *daemon = con->daemon;
41 int num_ready;
42 fd_set rs;
43 fd_set ws;
44 fd_set es;
45 MHD_socket maxsock;
46 struct timeval tv;
47 struct timeval *tvp;
48 time_t now;
49#if WINDOWS
50#ifdef HAVE_POLL
51 int extra_slot;
52#endif /* HAVE_POLL */
53#define EXTRA_SLOTS 1
54#else /* !WINDOWS */
55#define EXTRA_SLOTS 0
56#endif /* !WINDOWS */
57#ifdef HAVE_POLL
58 struct pollfd p[1 + EXTRA_SLOTS];
59#endif
60#undef EXTRA_SLOTS
61#ifdef HAVE_POLL
62 const bool use_poll = (MHD_ELS_POLL == daemon->event_loop_syscall);
63#else /* ! HAVE_POLL */
64 const bool use_poll = false;
65#endif /* ! HAVE_POLL */
66 bool was_suspended = false;
67
68 MHD_thread_init_(&con->pid);
69
70 while ( (! daemon->shutdown) &&
71 (MHD_REQUEST_CLOSED != con->request.state) )
72 {
73 const time_t timeout = daemon->connection_default_timeout;
74#ifdef UPGRADE_SUPPORT
75 struct MHD_UpgradeResponseHandle * const urh = con->request.urh;
76#else /* ! UPGRADE_SUPPORT */
77 static const void * const urh = NULL;
78#endif /* ! UPGRADE_SUPPORT */
79
80 if ( (con->suspended) &&
81 (NULL == urh) )
82 {
83 /* Connection was suspended, wait for resume. */
84 was_suspended = true;
85 if (! use_poll)
86 {
87 FD_ZERO (&rs);
88 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
89 &rs,
90 NULL,
91 FD_SETSIZE))
92 {
93 #ifdef HAVE_MESSAGES
94 MHD_DLOG (con->daemon,
95 MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
96 _("Failed to add FD to fd_set\n"));
97 #endif
98 goto exit;
99 }
100 if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
101 &rs,
102 NULL,
103 NULL,
104 NULL))
105 {
106 const int err = MHD_socket_get_error_();
107
108 if (MHD_SCKT_ERR_IS_EINTR_(err))
109 continue;
110#ifdef HAVE_MESSAGES
111 MHD_DLOG (con->daemon,
112 MHD_SC_UNEXPECTED_SELECT_ERROR,
113 _("Error during select (%d): `%s'\n"),
114 err,
115 MHD_socket_strerr_ (err));
116#endif
117 break;
118 }
119 }
120#ifdef HAVE_POLL
121 else /* use_poll */
122 {
123 p[0].events = POLLIN;
124 p[0].fd = MHD_itc_r_fd_ (daemon->itc);
125 p[0].revents = 0;
126 if (0 > MHD_sys_poll_ (p,
127 1,
128 -1))
129 {
130 if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_))
131 continue;
132#ifdef HAVE_MESSAGES
133 MHD_DLOG (con->daemon,
134 MHD_SC_UNEXPECTED_POLL_ERROR,
135 _("Error during poll: `%s'\n"),
136 MHD_socket_last_strerr_ ());
137#endif
138 break;
139 }
140 }
141#endif /* HAVE_POLL */
142 MHD_itc_clear_ (daemon->itc);
143 continue; /* Check again for resume. */
144 } /* End of "suspended" branch. */
145
146 if (was_suspended)
147 {
148 MHD_update_last_activity_ (con); /* Reset timeout timer. */
149 /* Process response queued during suspend and update states. */
150 MHD_connection_handle_idle (con);
151 was_suspended = false;
152 }
153
154 tvp = NULL;
155
156 if ( (MHD_EVENT_LOOP_INFO_BLOCK == con->request.event_loop_info)
157#ifdef HTTPS_SUPPORT
158 || ( (con->tls_read_ready) &&
159 (MHD_EVENT_LOOP_INFO_READ == con->request.event_loop_info) )
160#endif /* HTTPS_SUPPORT */
161 )
162 {
163 /* do not block: more data may be inside of TLS buffers waiting or
164 * application must provide response data */
165 tv.tv_sec = 0;
166 tv.tv_usec = 0;
167 tvp = &tv;
168 }
169 if ( (NULL == tvp) &&
170 (timeout > 0) )
171 {
172 now = MHD_monotonic_sec_counter();
173 if (now - con->last_activity > timeout)
174 tv.tv_sec = 0;
175 else
176 {
177 const time_t seconds_left = timeout - (now - con->last_activity);
178#if !defined(_WIN32) || defined(__CYGWIN__)
179 tv.tv_sec = seconds_left;
180#else /* _WIN32 && !__CYGWIN__ */
181 if (seconds_left > TIMEVAL_TV_SEC_MAX)
182 tv.tv_sec = TIMEVAL_TV_SEC_MAX;
183 else
184 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
185#endif /* _WIN32 && ! __CYGWIN__ */
186 }
187 tv.tv_usec = 0;
188 tvp = &tv;
189 }
190 if (! use_poll)
191 {
192 /* use select */
193 bool err_state = false;
194
195 FD_ZERO (&rs);
196 FD_ZERO (&ws);
197 FD_ZERO (&es);
198 maxsock = MHD_INVALID_SOCKET;
199 switch (con->request.event_loop_info)
200 {
201 case MHD_EVENT_LOOP_INFO_READ:
202 if (! MHD_add_to_fd_set_ (con->socket_fd,
203 &rs,
204 &maxsock,
205 FD_SETSIZE))
206 err_state = true;
207 break;
208 case MHD_EVENT_LOOP_INFO_WRITE:
209 if (! MHD_add_to_fd_set_ (con->socket_fd,
210 &ws,
211 &maxsock,
212 FD_SETSIZE))
213 err_state = true;
214 break;
215 case MHD_EVENT_LOOP_INFO_BLOCK:
216 if (! MHD_add_to_fd_set_ (con->socket_fd,
217 &es,
218 &maxsock,
219 FD_SETSIZE))
220 err_state = true;
221 break;
222 case MHD_EVENT_LOOP_INFO_CLEANUP:
223 /* how did we get here!? */
224 goto exit;
225 }
226#if WINDOWS
227 if (MHD_ITC_IS_VALID_(daemon->itc) )
228 {
229 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
230 &rs,
231 &maxsock,
232 FD_SETSIZE))
233 err_state = 1;
234 }
235#endif
236 if (err_state)
237 {
238#ifdef HAVE_MESSAGES
239 MHD_DLOG (con->daemon,
240 MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
241 _("Failed to add FD to fd_set\n"));
242#endif
243 goto exit;
244 }
245
246 num_ready = MHD_SYS_select_ (maxsock + 1,
247 &rs,
248 &ws,
249 NULL,
250 tvp);
251 if (num_ready < 0)
252 {
253 const int err = MHD_socket_get_error_();
254
255 if (MHD_SCKT_ERR_IS_EINTR_(err))
256 continue;
257#ifdef HAVE_MESSAGES
258 MHD_DLOG (con->daemon,
259 MHD_SC_UNEXPECTED_SELECT_ERROR,
260 _("Error during select (%d): `%s'\n"),
261 err,
262 MHD_socket_strerr_ (err));
263#endif
264 break;
265 }
266#if WINDOWS
267 /* Clear ITC before other processing so additional
268 * signals will trigger select() again */
269 if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
270 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
271 &rs)) )
272 MHD_itc_clear_ (daemon->itc);
273#endif
274 if (MHD_NO ==
275 call_handlers (con,
276 FD_ISSET (con->socket_fd,
277 &rs),
278 FD_ISSET (con->socket_fd,
279 &ws),
280 FD_ISSET (con->socket_fd,
281 &es)) )
282 goto exit;
283 }
284#ifdef HAVE_POLL
285 else
286 {
287 /* use poll */
288 memset (&p,
289 0,
290 sizeof (p));
291 p[0].fd = con->socket_fd;
292 switch (con->request.event_loop_info)
293 {
294 case MHD_EVENT_LOOP_INFO_READ:
295 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
296 break;
297 case MHD_EVENT_LOOP_INFO_WRITE:
298 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
299 break;
300 case MHD_EVENT_LOOP_INFO_BLOCK:
301 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
302 break;
303 case MHD_EVENT_LOOP_INFO_CLEANUP:
304 /* how did we get here!? */
305 goto exit;
306 }
307#if WINDOWS
308 extra_slot = 0;
309 if (MHD_ITC_IS_VALID_(daemon->itc))
310 {
311 p[1].events |= POLLIN;
312 p[1].fd = MHD_itc_r_fd_ (daemon->itc);
313 p[1].revents = 0;
314 extra_slot = 1;
315 }
316#endif
317 if (MHD_sys_poll_ (p,
318#if WINDOWS
319 1 + extra_slot,
320#else
321 1,
322#endif
323 (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
324 {
325 if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_))
326 continue;
327#ifdef HAVE_MESSAGES
328 MHD_DLOG (con->daemon,
329 MHD_SC_UNEXPECTED_POLL_ERROR,
330 _("Error during poll: `%s'\n"),
331 MHD_socket_last_strerr_ ());
332#endif
333 break;
334 }
335#if WINDOWS
336 /* Clear ITC before other processing so additional
337 * signals will trigger poll() again */
338 if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
339 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
340 MHD_itc_clear_ (daemon->itc);
341#endif
342 if (MHD_NO ==
343 call_handlers (con,
344 0 != (p[0].revents & POLLIN),
345 0 != (p[0].revents & POLLOUT),
346 0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
347 goto exit;
348 }
349#endif
350#ifdef UPGRADE_SUPPORT
351 if (MHD_REQUEST_UPGRADE == con->request.state)
352 {
353 /* Normal HTTP processing is finished,
354 * notify application. */
355 if ( (NULL != con->request.response->termination_cb) &&
356 (con->request.client_aware) )
357 con->request.response->termination_cb
358 (con->request.response->termination_cb_cls,
359 MHD_REQUEST_TERMINATED_COMPLETED_OK,
360 con->request.client_context);
361 con->request.client_aware = false;
362
363 thread_main_connection_upgrade (con);
364 /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
365
366 /* "Upgraded" data will not be used in this thread from this point. */
367 con->request.urh->clean_ready = true;
368 /* If 'urh->was_closed' set to true, connection will be
369 * moved immediately to cleanup list. Otherwise connection
370 * will stay in suspended list until 'urh' will be marked
371 * with 'was_closed' by application. */
372 MHD_resume_connection (con);
373
374 /* skip usual clean up */
375 return (MHD_THRD_RTRN_TYPE_) 0;
376 }
377#endif /* UPGRADE_SUPPORT */
378 }
379 if (MHD_REQUEST_IN_CLEANUP != con->request.state)
380 {
381#if DEBUG_CLOSE
382#ifdef HAVE_MESSAGES
383 MHD_DLOG (con->daemon,
384 MHD_SC_THREAD_TERMINATING,
385 _("Processing thread terminating. Closing connection\n"));
386#endif
387#endif
388 if (MHD_REQUEST_CLOSED != con->request.state)
389 MHD_connection_close_ (con,
390 (daemon->shutdown) ?
391 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN:
392 MHD_REQUEST_TERMINATED_WITH_ERROR);
393 MHD_connection_handle_idle (con);
394 }
395exit:
396 if (NULL != con->request.response)
397 {
398 MHD_response_queue_for_destroy (con->request.response);
399 con->request.response = NULL;
400 }
401
402 if (MHD_INVALID_SOCKET != con->socket_fd)
403 {
404 shutdown (con->socket_fd,
405 SHUT_WR);
406 /* 'socket_fd' can be used in other thread to signal shutdown.
407 * To avoid data races, do not close socket here. Daemon will
408 * use more connections only after cleanup anyway. */
409 }
410 return (MHD_THRD_RTRN_TYPE_) 0;
411}
412
413
414/**
415 * Add another client connection to the set of connections
416 * managed by MHD. This API is usually not needed (since
417 * MHD will accept inbound connections on the server socket).
418 * Use this API in special cases, for example if your HTTP
419 * server is behind NAT and needs to connect out to the
420 * HTTP client.
421 *
422 * The given client socket will be managed (and closed!) by MHD after
423 * this call and must no longer be used directly by the application
424 * afterwards.
425 *
426 * @param daemon daemon that manages the connection
427 * @param client_socket socket to manage (MHD will expect
428 * to receive an HTTP request from this socket next).
429 * @param addr IP address of the client
430 * @param addrlen number of bytes in @a addr
431 * @param external_add perform additional operations needed due
432 * to the application calling us directly
433 * @param non_blck indicate that socket in non-blocking mode
434 * @return #MHD_SC_OK on success
435 */
436static enum MHD_StatusCode
437internal_add_connection (struct MHD_Daemon *daemon,
438 MHD_socket client_socket,
439 const struct sockaddr *addr,
440 socklen_t addrlen,
441 bool external_add,
442 bool non_blck)
443{
444 enum MHD_StatusCode sc;
445 struct MHD_Connection *connection;
446 int eno = 0;
447
448 /* Direct add to master daemon could happen only with "external" add mode. */
449 mhd_assert ( (NULL == daemon->worker_pool) ||
450 (external_add) );
451 if ( (external_add) &&
452 (NULL != daemon->worker_pool) )
453 {
454 unsigned int i;
455
456 /* have a pool, try to find a pool with capacity; we use the
457 socket as the initial offset into the pool for load
458 balancing */
459 for (i = 0; i < daemon->worker_pool_size; ++i)
460 {
461 struct MHD_Daemon * const worker =
462 &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
463 if (worker->connections < worker->global_connection_limit)
464 return internal_add_connection (worker,
465 client_socket,
466 addr,
467 addrlen,
468 true,
469 non_blck);
470 }
471 /* all pools are at their connection limit, must refuse */
472 MHD_socket_close_chk_ (client_socket);
473#if ENFILE
474 errno = ENFILE;
475#endif
476 return MHD_SC_LIMIT_CONNECTIONS_REACHED;
477 }
478
479 if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
480 NULL)) &&
481 (MHD_ELS_SELECT == daemon->event_loop_syscall) )
482 {
483#ifdef HAVE_MESSAGES
484 MHD_DLOG (daemon,
485 MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
486 _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
487 (int) client_socket,
488 (int) FD_SETSIZE);
489#endif
490 MHD_socket_close_chk_ (client_socket);
491#if EINVAL
492 errno = EINVAL;
493#endif
494 return MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE;
495 }
496
497#ifdef MHD_socket_nosignal_
498 if (! MHD_socket_nosignal_ (client_socket))
499 {
500#ifdef HAVE_MESSAGES
501 MHD_DLOG (daemon,
502 MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED,
503 _("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
504 MHD_socket_last_strerr_());
505#endif
506#ifndef MSG_NOSIGNAL
507 /* Cannot use socket as it can produce SIGPIPE. */
508#ifdef ENOTSOCK
509 errno = ENOTSOCK;
510#endif /* ENOTSOCK */
511 return MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED;
512#endif /* ! MSG_NOSIGNAL */
513 }
514#endif /* MHD_socket_nosignal_ */
515
516
517#ifdef HAVE_MESSAGES
518#if DEBUG_CONNECT
519 MHD_DLOG (daemon,
520 MHD_SC_CONNECTION_ACCEPTED,
521 _("Accepted connection on socket %d\n"),
522 client_socket);
523#endif
524#endif
525 if ( (daemon->connections == daemon->global_connection_limit) ||
526 (MHD_NO == MHD_ip_limit_add (daemon,
527 addr,
528 addrlen)) )
529 {
530 /* above connection limit - reject */
531#ifdef HAVE_MESSAGES
532 MHD_DLOG (daemon,
533 MHD_SC_LIMIT_CONNECTIONS_REACHED,
534 _("Server reached connection limit. Closing inbound connection.\n"));
535#endif
536 MHD_socket_close_chk_ (client_socket);
537#if ENFILE
538 errno = ENFILE;
539#endif
540 return MHD_SC_LIMIT_CONNECTIONS_REACHED;
541 }
542
543 /* apply connection acceptance policy if present */
544 if ( (NULL != daemon->accept_policy_cb) &&
545 (MHD_NO ==
546 daemon->accept_policy_cb (daemon->accept_policy_cb_cls,
547 addr,
548 addrlen)) )
549 {
550#if DEBUG_CLOSE
551#ifdef HAVE_MESSAGES
552 MHD_DLOG (daemon,
553 MHD_SC_ACCEPT_POLICY_REJECTED,
554 _("Connection rejected by application. Closing connection.\n"));
555#endif
556#endif
557 MHD_socket_close_chk_ (client_socket);
558 MHD_ip_limit_del (daemon,
559 addr,
560 addrlen);
561#if EACCESS
562 errno = EACCESS;
563#endif
564 return MHD_SC_ACCEPT_POLICY_REJECTED;
565 }
566
567 if (NULL ==
568 (connection = MHD_calloc_ (1,
569 sizeof (struct MHD_Connection))))
570 {
571 eno = errno;
572#ifdef HAVE_MESSAGES
573 MHD_DLOG (daemon,
574 MHD_SC_CONNECTION_MALLOC_FAILURE,
575 "Error allocating memory: %s\n",
576 MHD_strerror_ (errno));
577#endif
578 MHD_socket_close_chk_ (client_socket);
579 MHD_ip_limit_del (daemon,
580 addr,
581 addrlen);
582 errno = eno;
583 return MHD_SC_CONNECTION_MALLOC_FAILURE;
584 }
585 connection->request.pool
586 = MHD_pool_create (daemon->connection_memory_limit_b);
587 if (NULL == connection->request.pool)
588 {
589#ifdef HAVE_MESSAGES
590 MHD_DLOG (daemon,
591 MHD_SC_POOL_MALLOC_FAILURE,
592 _("Error allocating memory: %s\n"),
593 MHD_strerror_ (errno));
594#endif
595 MHD_socket_close_chk_ (client_socket);
596 MHD_ip_limit_del (daemon,
597 addr,
598 addrlen);
599 free (connection);
600#if ENOMEM
601 errno = ENOMEM;
602#endif
603 return MHD_SC_POOL_MALLOC_FAILURE;
604 }
605
606 connection->connection_timeout = daemon->connection_default_timeout;
607 memcpy (&connection->addr,
608 addr,
609 addrlen);
610 connection->addr_len = addrlen;
611 connection->socket_fd = client_socket;
612 connection->sk_nonblck = non_blck;
613 connection->daemon = daemon;
614 connection->last_activity = MHD_monotonic_sec_counter();
615
616#ifdef HTTPS_SUPPORT
617 if (NULL != daemon->tls_api)
618 {
619 connection->tls_cs
620 = daemon->tls_api->setup_connection (daemon->tls_api->cls,
621 NULL /* FIXME */);
622 if (NULL == connection->tls_cs)
623 {
624 eno = EINVAL;
625 sc = -1; // FIXME!
626 goto cleanup;
627 }
628 }
629 else
630#endif /* ! HTTPS_SUPPORT */
631 /* set default connection handlers */
632 MHD_set_http_callbacks_ (connection);
633
634 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
635 /* Firm check under lock. */
636 if (daemon->connections >= daemon->global_connection_limit)
637 {
638 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
639 /* above connection limit - reject */
640#ifdef HAVE_MESSAGES
641 MHD_DLOG (daemon,
642 MHD_SC_LIMIT_CONNECTIONS_REACHED,
643 _("Server reached connection limit. Closing inbound connection.\n"));
644#endif
645#if ENFILE
646 eno = ENFILE;
647#endif
648 sc = MHD_SC_LIMIT_CONNECTIONS_REACHED;
649 goto cleanup;
650 }
651 daemon->connections++;
652 if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_model)
653 {
654 XDLL_insert (daemon->normal_timeout_head,
655 daemon->normal_timeout_tail,
656 connection);
657 }
658 DLL_insert (daemon->connections_head,
659 daemon->connections_tail,
660 connection);
661 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
662
663 if (NULL != daemon->notify_connection_cb)
664 daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
665 connection,
666 MHD_CONNECTION_NOTIFY_STARTED);
667
668 /* attempt to create handler thread */
669 if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model)
670 {
671 if (! MHD_create_named_thread_ (&connection->pid,
672 "MHD-connection",
673 daemon->thread_stack_limit_b,
674 &thread_main_handle_connection,
675 connection))
676 {
677 eno = errno;
678#ifdef HAVE_MESSAGES
679 MHD_DLOG (daemon,
680 MHD_SC_THREAD_LAUNCH_FAILURE,
681 "Failed to create a thread: %s\n",
682 MHD_strerror_ (eno));
683#endif
684 sc = MHD_SC_THREAD_LAUNCH_FAILURE;
685 goto cleanup;
686 }
687 }
688 else
689 {
690 connection->pid = daemon->pid;
691 }
692#ifdef EPOLL_SUPPORT
693 if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
694 {
695 if ( (! daemon->enable_turbo) ||
696 (external_add))
697 { /* Do not manipulate EReady DL-list in 'external_add' mode. */
698 struct epoll_event event;
699
700 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
701 event.data.ptr = connection;
702 if (0 != epoll_ctl (daemon->epoll_fd,
703 EPOLL_CTL_ADD,
704 client_socket,
705 &event))
706 {
707 eno = errno;
708#ifdef HAVE_MESSAGES
709 MHD_DLOG (daemon,
710 MHD_SC_EPOLL_CTL_ADD_FAILED,
711 _("Call to epoll_ctl failed: %s\n"),
712 MHD_socket_last_strerr_ ());
713#endif
714 sc = MHD_SC_EPOLL_CTL_ADD_FAILED;
715 goto cleanup;
716 }
717 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
718 }
719 else
720 {
721 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
722 | MHD_EPOLL_STATE_IN_EREADY_EDLL;
723 EDLL_insert (daemon->eready_head,
724 daemon->eready_tail,
725 connection);
726 }
727 }
728 else /* This 'else' is combined with next 'if'. */
729#endif
730 if ( (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_model) &&
731 (external_add) &&
732 (MHD_ITC_IS_VALID_(daemon->itc)) &&
733 (! MHD_itc_activate_ (daemon->itc,
734 "n")) )
735 {
736#ifdef HAVE_MESSAGES
737 MHD_DLOG (daemon,
738 MHD_SC_ITC_USE_FAILED,
739 _("Failed to signal new connection via inter-thread communication channel."));
740#endif
741 sc = MHD_SC_ITC_USE_FAILED;
742 }
743 return MHD_SC_OK;
744
745 cleanup:
746 if (NULL != daemon->notify_connection_cb)
747 daemon->notify_connection_cb (daemon->notify_connection_cb_cls,
748 connection,
749 MHD_CONNECTION_NOTIFY_CLOSED);
750#ifdef HTTPS_SUPPORT
751 if (NULL != connection->tls_cs)
752 daemon->tls_api->teardown_connection (daemon->tls_api->cls,
753 connection->tls_cs);
754#endif /* HTTPS_SUPPORT */
755 MHD_socket_close_chk_ (client_socket);
756 MHD_ip_limit_del (daemon,
757 addr,
758 addrlen);
759 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
760 if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_model)
761 {
762 XDLL_remove (daemon->normal_timeout_head,
763 daemon->normal_timeout_tail,
764 connection);
765 }
766 DLL_remove (daemon->connections_head,
767 daemon->connections_tail,
768 connection);
769 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
770 MHD_pool_destroy (connection->request.pool);
771 free (connection);
772 if (0 != eno)
773 errno = eno;
774 else
775 errno = EINVAL;
776 return sc;
777}
778
779
780/**
781 * Add another client connection to the set of connections managed by
782 * MHD. This API is usually not needed (since MHD will accept inbound
783 * connections on the server socket). Use this API in special cases,
784 * for example if your HTTP server is behind NAT and needs to connect
785 * out to the HTTP client, or if you are building a proxy.
786 *
787 * If you use this API in conjunction with a internal select or a
788 * thread pool, you must set the option #MHD_USE_ITC to ensure that
789 * the freshly added connection is immediately processed by MHD.
790 *
791 * The given client socket will be managed (and closed!) by MHD after
792 * this call and must no longer be used directly by the application
793 * afterwards.
794 *
795 * @param daemon daemon that manages the connection
796 * @param client_socket socket to manage (MHD will expect
797 * to receive an HTTP request from this socket next).
798 * @param addr IP address of the client
799 * @param addrlen number of bytes in @a addr
800 * @return #MHD_YES on success, #MHD_NO if this daemon could
801 * not handle the connection (i.e. malloc() failed, etc).
802 * The socket will be closed in any case; `errno` is
803 * set to indicate further details about the error.
804 * @ingroup specialized
805 */
806enum MHD_StatusCode
807MHD_daemon_add_connection (struct MHD_Daemon *daemon,
808 MHD_socket client_socket,
809 const struct sockaddr *addr,
810 socklen_t addrlen)
811{
812 bool sk_nonbl;
813
814 if (! MHD_socket_nonblocking_ (client_socket))
815 {
816#ifdef HAVE_MESSAGES
817 MHD_DLOG (daemon,
818 MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
819 _("Failed to set nonblocking mode on new client socket: %s\n"),
820 MHD_socket_last_strerr_());
821#endif
822 sk_nonbl = false;
823 }
824 else
825 {
826 sk_nonbl = true;
827 }
828
829 if ( (daemon->enable_turbo) &&
830 (! MHD_socket_noninheritable_ (client_socket)) )
831 {
832#ifdef HAVE_MESSAGES
833 MHD_DLOG (daemon,
834 MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
835 _("Failed to set noninheritable mode on new client socket.\n"));
836#endif
837 }
838 return internal_add_connection (daemon,
839 client_socket,
840 addr,
841 addrlen,
842 true,
843 sk_nonbl);
844}
845
846
847/**
848 * Accept an incoming connection and create the MHD_Connection object
849 * for it. This function also enforces policy by way of checking with
850 * the accept policy callback. @remark To be called only from thread
851 * that process daemon's select()/poll()/etc.
852 *
853 * @param daemon handle with the listen socket
854 * @return #MHD_SC_OK on success
855 */
856enum MHD_StatusCode
857MHD_accept_connection_ (struct MHD_Daemon *daemon)
858{
859 struct sockaddr_storage addrstorage;
860 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
861 socklen_t addrlen;
862 MHD_socket s;
863 MHD_socket fd;
864 bool sk_nonbl;
865
866 addrlen = sizeof (addrstorage);
867 memset (addr,
868 0,
869 sizeof (addrstorage));
870 if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_socket)) ||
871 (daemon->was_quiesced) )
872 return MHD_SC_DAEMON_ALREADY_QUIESCED;
873#ifdef USE_ACCEPT4
874 s = accept4 (fd,
875 addr,
876 &addrlen,
877 MAYBE_SOCK_CLOEXEC | MAYBE_SOCK_NONBLOCK);
878 sk_nonbl = (0 != MAYBE_SOCK_NONBLOCK);
879#else /* ! USE_ACCEPT4 */
880 s = accept (fd,
881 addr,
882 &addrlen);
883 sk_nonbl = false;
884#endif /* ! USE_ACCEPT4 */
885 if ( (MHD_INVALID_SOCKET == s) ||
886 (addrlen <= 0) )
887 {
888 const int err = MHD_socket_get_error_ ();
889
890 /* This could be a common occurance with multiple worker threads */
891 if (MHD_SCKT_ERR_IS_ (err,
892 MHD_SCKT_EINVAL_))
893 return MHD_SC_DAEMON_ALREADY_SHUTDOWN; /* can happen during shutdown, let's hope this is the cause... */
894 if (MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err))
895 return MHD_SC_ACCEPT_FAST_DISCONNECT; /* do not print error if client just disconnected early */
896 if (MHD_SCKT_ERR_IS_EAGAIN_ (err) )
897 return MHD_SC_ACCEPT_FAILED_EAGAIN;
898 if (MHD_INVALID_SOCKET != s)
899 {
900 MHD_socket_close_chk_ (s);
901 }
902 if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
903 {
904 /* system/process out of resources */
905 if (0 == daemon->connections)
906 {
907#ifdef HAVE_MESSAGES
908 /* Not setting 'at_limit' flag, as there is no way it
909 would ever be cleared. Instead trying to produce
910 bit fat ugly warning. */
911 MHD_DLOG (daemon,
912 MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY,
913 _("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"));
914#endif
915 return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED_INSTANTLY;
916 }
917 else
918 {
919 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
920 daemon->at_limit = true;
921 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
922#ifdef HAVE_MESSAGES
923 MHD_DLOG (daemon,
924 MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED,
925 _("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
926 (unsigned int) daemon->connections);
927#endif
928 return MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED;
929 }
930 }
931#ifdef HAVE_MESSAGES
932 MHD_DLOG (daemon,
933 MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY,
934 _("Error accepting connection: %s\n"),
935 MHD_socket_strerr_(err));
936#endif
937 return MHD_SC_ACCEPT_FAILED_UNEXPECTEDLY;
938 }
939#if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
940 if (! MHD_socket_nonblocking_ (s))
941 {
942#ifdef HAVE_MESSAGES
943 MHD_DLOG (daemon,
944 MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED,
945 _("Failed to set nonblocking mode on incoming connection socket: %s\n"),
946 MHD_socket_last_strerr_());
947#endif
948 }
949 else
950 sk_nonbl = true;
951#endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
952#if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
953 if (! MHD_socket_noninheritable_ (s))
954 {
955#ifdef HAVE_MESSAGES
956 MHD_DLOG (daemon,
957 MHD_SC_ACCEPT_CONFIGURE_NOINHERIT_FAILED,
958 _("Failed to set noninheritable mode on incoming connection socket.\n"));
959#endif
960 }
961#endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
962#ifdef HAVE_MESSAGES
963#if DEBUG_CONNECT
964 MHD_DLOG (daemon,
965 MHD_SC_CONNECTION_ACCEPTED,
966 _("Accepted connection on socket %d\n"),
967 s);
968#endif
969#endif
970 return internal_add_connection (daemon,
971 s,
972 addr,
973 addrlen,
974 false,
975 sk_nonbl);
976}
977
978/* end of connection_add.c */