aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c183
1 files changed, 132 insertions, 51 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index ca488593..6888db28 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -2343,76 +2343,37 @@ psk_gnutls_adapter (gnutls_session_t session,
2343 2343
2344 2344
2345/** 2345/**
2346 * Add another client connection to the set of connections 2346 * Do basic preparation work on the new incoming connection.
2347 * managed by MHD. This API is usually not needed (since
2348 * MHD will accept inbound connections on the server socket).
2349 * Use this API in special cases, for example if your HTTP
2350 * server is behind NAT and needs to connect out to the
2351 * HTTP client.
2352 * 2347 *
2353 * The given client socket will be managed (and closed!) by MHD after 2348 * This function do all preparation that is possible outside main daemon
2354 * this call and must no longer be used directly by the application 2349 * thread.
2355 * afterwards. 2350 * @remark Could be called from any thread.
2356 * 2351 *
2357 * @param daemon daemon that manages the connection 2352 * @param daemon daemon that manages the connection
2358 * @param client_socket socket to manage (MHD will expect 2353 * @param client_socket socket to manage (MHD will expect
2359 * to receive an HTTP request from this socket next). 2354 * to receive an HTTP request from this socket next).
2360 * @param addr IP address of the client 2355 * @param addr IP address of the client
2361 * @param addrlen number of bytes in @a addr 2356 * @param addrlen number of bytes in @a addr
2362 * @param external_add perform additional operations needed due
2363 * to the application calling us directly
2364 * @param non_blck indicate that socket in non-blocking mode 2357 * @param non_blck indicate that socket in non-blocking mode
2358 * @param pconnection pointer to variable that receive pointer to
2359 * the new connection structure.
2365 * @return #MHD_YES on success, #MHD_NO if this daemon could 2360 * @return #MHD_YES on success, #MHD_NO if this daemon could
2366 * not handle the connection (i.e. malloc failed, etc). 2361 * not handle the connection (i.e. malloc failed, etc).
2367 * The socket will be closed in any case; 'errno' is 2362 * The socket will be closed in case of error; 'errno' is
2368 * set to indicate further details about the error. 2363 * set to indicate further details about the error.
2369 */ 2364 */
2370static enum MHD_Result 2365static enum MHD_Result
2371internal_add_connection (struct MHD_Daemon *daemon, 2366new_connection_prepare_ (struct MHD_Daemon *daemon,
2372 MHD_socket client_socket, 2367 MHD_socket client_socket,
2373 const struct sockaddr *addr, 2368 const struct sockaddr *addr,
2374 socklen_t addrlen, 2369 socklen_t addrlen,
2375 bool external_add, 2370 bool non_blck,
2376 bool non_blck) 2371 struct MHD_Connection **pconnection)
2377{ 2372{
2378 struct MHD_Connection *connection; 2373 struct MHD_Connection *connection;
2379 int eno = 0; 2374 int eno = 0;
2380 2375
2381#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 2376 mhd_assert (NULL != pconnection);
2382 /* Direct add to master daemon could never happen. */
2383 mhd_assert ((NULL == daemon->worker_pool));
2384#endif
2385
2386 if ( (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
2387 (! MHD_SCKT_FD_FITS_FDSET_ (client_socket, NULL)) )
2388 {
2389#ifdef HAVE_MESSAGES
2390 MHD_DLOG (daemon,
2391 _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2392 (int) client_socket,
2393 (int) FD_SETSIZE);
2394#endif
2395 MHD_socket_close_chk_ (client_socket);
2396#if ENFILE
2397 errno = ENFILE;
2398#endif
2399 return MHD_NO;
2400 }
2401
2402 if ( (0 == (daemon->options & MHD_USE_EPOLL)) &&
2403 (! non_blck) )
2404 {
2405#ifdef HAVE_MESSAGES
2406 MHD_DLOG (daemon,
2407 _ ("Epoll mode supports only non-blocking sockets\n"));
2408#endif
2409 MHD_socket_close_chk_ (client_socket);
2410#if EINVAL
2411 errno = EINVAL;
2412#endif
2413 return MHD_NO;
2414 }
2415
2416#ifdef MHD_socket_nosignal_ 2377#ifdef MHD_socket_nosignal_
2417 if (! MHD_socket_nosignal_ (client_socket)) 2378 if (! MHD_socket_nosignal_ (client_socket))
2418 { 2379 {
@@ -2628,11 +2589,52 @@ internal_add_connection (struct MHD_Daemon *daemon,
2628 gnutls_certificate_server_set_request (connection->tls_session, 2589 gnutls_certificate_server_set_request (connection->tls_session,
2629 GNUTLS_CERT_REQUEST); 2590 GNUTLS_CERT_REQUEST);
2630#else /* ! HTTPS_SUPPORT */ 2591#else /* ! HTTPS_SUPPORT */
2592 MHD_socket_close_chk_ (client_socket);
2593 MHD_ip_limit_del (daemon,
2594 addr,
2595 addrlen);
2596 free (connection->addr);
2597 free (connection);
2598 MHD_PANIC (_ ("TLS connection on non-TLS daemon.\n"));
2631 eno = EINVAL; 2599 eno = EINVAL;
2632 goto cleanup; 2600 return MHD_NO;
2633#endif /* ! HTTPS_SUPPORT */ 2601#endif /* ! HTTPS_SUPPORT */
2634 } 2602 }
2635 2603
2604 *pconnection = connection;
2605 return MHD_YES;
2606}
2607
2608
2609/**
2610 * Finally insert the new connection to the list of connections
2611 * served by the daemon.
2612 * @remark To be called only from thread that process
2613 * daemon's select()/poll()/etc.
2614 *
2615 * @param daemon daemon that manages the connection
2616 * @param client_socket socket to manage (MHD will expect
2617 * to receive an HTTP request from this socket next).
2618 * @param addr IP address of the client
2619 * @param addrlen number of bytes in @a addr
2620 * @param external_add perform additional operations needed due
2621 * to the application calling us directly
2622 * @param connection the newly created connection
2623 * @return #MHD_YES on success, #MHD_NO if this daemon could
2624 * not handle the connection (i.e. malloc failed, etc).
2625 * The socket will be closed in any case; 'errno' is
2626 * set to indicate further details about the error.
2627 */
2628static enum MHD_Result
2629new_connection_insert_ (struct MHD_Daemon *daemon,
2630 MHD_socket client_socket,
2631 const struct sockaddr *addr,
2632 socklen_t addrlen,
2633 bool external_add,
2634 struct MHD_Connection *connection)
2635{
2636 int eno = 0;
2637
2636#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 2638#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2637 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 2639 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2638#endif 2640#endif
@@ -2782,6 +2784,85 @@ cleanup:
2782 2784
2783 2785
2784/** 2786/**
2787 * Add another client connection to the set of connections
2788 * managed by MHD. This API is usually not needed (since
2789 * MHD will accept inbound connections on the server socket).
2790 * Use this API in special cases, for example if your HTTP
2791 * server is behind NAT and needs to connect out to the
2792 * HTTP client.
2793 *
2794 * The given client socket will be managed (and closed!) by MHD after
2795 * this call and must no longer be used directly by the application
2796 * afterwards.
2797 *
2798 * @param daemon daemon that manages the connection
2799 * @param client_socket socket to manage (MHD will expect
2800 * to receive an HTTP request from this socket next).
2801 * @param addr IP address of the client
2802 * @param addrlen number of bytes in @a addr
2803 * @param external_add perform additional operations needed due
2804 * to the application calling us directly
2805 * @param non_blck indicate that socket in non-blocking mode
2806 * @return #MHD_YES on success, #MHD_NO if this daemon could
2807 * not handle the connection (i.e. malloc failed, etc).
2808 * The socket will be closed in any case; 'errno' is
2809 * set to indicate further details about the error.
2810 */
2811static enum MHD_Result
2812internal_add_connection (struct MHD_Daemon *daemon,
2813 MHD_socket client_socket,
2814 const struct sockaddr *addr,
2815 socklen_t addrlen,
2816 bool external_add,
2817 bool non_blck)
2818{
2819 struct MHD_Connection *connection;
2820
2821#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2822 /* Direct add to master daemon could never happen. */
2823 mhd_assert ((NULL == daemon->worker_pool));
2824#endif
2825
2826 if ( (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
2827 (! MHD_SCKT_FD_FITS_FDSET_ (client_socket, NULL)) )
2828 {
2829#ifdef HAVE_MESSAGES
2830 MHD_DLOG (daemon,
2831 _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2832 (int) client_socket,
2833 (int) FD_SETSIZE);
2834#endif
2835 MHD_socket_close_chk_ (client_socket);
2836#if ENFILE
2837 errno = ENFILE;
2838#endif
2839 return MHD_NO;
2840 }
2841
2842 if ( (0 == (daemon->options & MHD_USE_EPOLL)) &&
2843 (! non_blck) )
2844 {
2845#ifdef HAVE_MESSAGES
2846 MHD_DLOG (daemon,
2847 _ ("Epoll mode supports only non-blocking sockets\n"));
2848#endif
2849 MHD_socket_close_chk_ (client_socket);
2850#if EINVAL
2851 errno = EINVAL;
2852#endif
2853 return MHD_NO;
2854 }
2855
2856 if (MHD_NO == new_connection_prepare_ (daemon, client_socket, addr, addrlen,
2857 non_blck, &connection))
2858 return MHD_NO;
2859
2860 return new_connection_insert_ (daemon, client_socket, addr, addrlen,
2861 external_add, connection);
2862}
2863
2864
2865/**
2785 * Internal version of ::MHD_suspend_connection(). 2866 * Internal version of ::MHD_suspend_connection().
2786 * 2867 *
2787 * @remark In thread-per-connection mode: can be called from any thread, 2868 * @remark In thread-per-connection mode: can be called from any thread,