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.c257
1 files changed, 131 insertions, 126 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index b320177a..a96ec9ae 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -2736,166 +2736,171 @@ new_connection_process_ (struct MHD_Daemon *daemon,
2736 * NUMA and/or complex cache hierarchy. */ 2736 * NUMA and/or complex cache hierarchy. */
2737 connection->pool = MHD_pool_create (daemon->pool_size); 2737 connection->pool = MHD_pool_create (daemon->pool_size);
2738 if (NULL == connection->pool) 2738 if (NULL == connection->pool)
2739 { 2739 { /* 'pool' creation failed */
2740#ifdef HAVE_MESSAGES 2740#ifdef HAVE_MESSAGES
2741 MHD_DLOG (daemon, 2741 MHD_DLOG (daemon,
2742 _ ("Error allocating memory: %s\n"), 2742 _ ("Error allocating memory: %s\n"),
2743 MHD_strerror_ (errno)); 2743 MHD_strerror_ (errno));
2744#endif 2744#endif
2745 MHD_socket_close_chk_ (connection->socket_fd);
2746 MHD_ip_limit_del (daemon,
2747 connection->addr,
2748 connection->addr_len);
2749 free (connection);
2750#if ENOMEM 2745#if ENOMEM
2751 errno = ENOMEM; 2746 eno = ENOMEM;
2752#endif 2747#endif
2753 return MHD_NO; 2748 (void) 0; /* Mute possible compiler warning */
2754 } 2749 }
2755 2750 else
2756#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 2751 { /* 'pool' creation succeed */
2757 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 2752 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2758#endif 2753 /* Firm check under lock. */
2759 /* Firm check under lock. */ 2754 if (daemon->connections >= daemon->connection_limit)
2760 if (daemon->connections >= daemon->connection_limit) 2755 { /* Connections limit */
2761 {
2762#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2763 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2764#endif
2765 /* above connection limit - reject */
2766#ifdef HAVE_MESSAGES 2756#ifdef HAVE_MESSAGES
2767 MHD_DLOG (daemon, 2757 MHD_DLOG (daemon,
2768 _ ( 2758 _ ("Server reached connection limit. "
2769 "Server reached connection limit. Closing inbound connection.\n")); 2759 "Closing inbound connection.\n"));
2770#endif 2760#endif
2771#if ENFILE 2761#if ENFILE
2772 eno = ENFILE; 2762 eno = ENFILE;
2773#endif
2774 goto cleanup;
2775 }
2776 daemon->connections++;
2777 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2778 {
2779 XDLL_insert (daemon->normal_timeout_head,
2780 daemon->normal_timeout_tail,
2781 connection);
2782 }
2783 DLL_insert (daemon->connections_head,
2784 daemon->connections_tail,
2785 connection);
2786#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2787 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2788#endif 2763#endif
2789 if (NULL != daemon->notify_connection) 2764 (void) 0; /* Mute possible compiler warning */
2790 daemon->notify_connection (daemon->notify_connection_cls, 2765 }
2791 connection, 2766 else
2792 &connection->socket_context, 2767 { /* Have space for new connection */
2793 MHD_CONNECTION_NOTIFY_STARTED); 2768 daemon->connections++;
2794#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 2769 DLL_insert (daemon->connections_head,
2795 /* attempt to create handler thread */ 2770 daemon->connections_tail,
2796 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 2771 connection);
2797 { 2772 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2798 if (! MHD_create_named_thread_ (&connection->pid, 2773 {
2799 "MHD-connection", 2774 XDLL_insert (daemon->normal_timeout_head,
2800 daemon->thread_stack_size, 2775 daemon->normal_timeout_tail,
2801 &thread_main_handle_connection, 2776 connection);
2802 connection)) 2777 }
2803 { 2778 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2804 eno = errno; 2779 if (NULL != daemon->notify_connection)
2780 daemon->notify_connection (daemon->notify_connection_cls,
2781 connection,
2782 &connection->socket_context,
2783 MHD_CONNECTION_NOTIFY_STARTED);
2784#ifdef MHD_USE_THREADS
2785 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2786 {
2787 mhd_assert (0 == (daemon->options & MHD_USE_EPOLL));
2788 if (! MHD_create_named_thread_ (&connection->pid,
2789 "MHD-connection",
2790 daemon->thread_stack_size,
2791 &thread_main_handle_connection,
2792 connection))
2793 {
2794 eno = errno;
2805#ifdef HAVE_MESSAGES 2795#ifdef HAVE_MESSAGES
2806#ifdef EAGAIN 2796#ifdef EAGAIN
2807 if (EAGAIN == eno) 2797 if (EAGAIN == eno)
2808 MHD_DLOG (daemon, 2798 MHD_DLOG (daemon,
2809 _ ("Failed to create a new thread because it would have " \ 2799 _ ("Failed to create a new thread because it would "
2810 "exceeded the system limit on the number of threads or " \ 2800 "have exceeded the system limit on the number of "
2811 "no system resources available.\n")); 2801 "threads or no system resources available.\n"));
2812 else 2802 else
2813#endif /* EAGAIN */ 2803#endif /* EAGAIN */
2814 MHD_DLOG (daemon, 2804 MHD_DLOG (daemon,
2815 _ ("Failed to create a thread: %s\n"), 2805 _ ("Failed to create a thread: %s\n"),
2816 MHD_strerror_ (eno)); 2806 MHD_strerror_ (eno));
2817#endif /* HAVE_MESSAGES */ 2807#endif /* HAVE_MESSAGES */
2818 goto cleanup; 2808 }
2819 } 2809 else /* New thread has been created successfully */
2820 } 2810 return MHD_YES; /* *** Function success exit point *** */
2821 else 2811 }
2822 connection->pid = daemon->pid; 2812 else
2823#endif 2813#else /* ! MHD_USE_THREADS */
2814 if (1)
2815#endif /* ! MHD_USE_THREADS */
2816 { /* No 'thread-per-connection' */
2817#ifdef MHD_USE_THREADS
2818 connection->pid = daemon->pid;
2819#endif /* MHD_USE_THREADS */
2824#ifdef EPOLL_SUPPORT 2820#ifdef EPOLL_SUPPORT
2825 if (0 != (daemon->options & MHD_USE_EPOLL)) 2821 if (0 != (daemon->options & MHD_USE_EPOLL))
2826 { 2822 {
2827 if (0 == (daemon->options & MHD_USE_TURBO)) 2823 if (0 == (daemon->options & MHD_USE_TURBO))
2828 { 2824 {
2829 struct epoll_event event; 2825 struct epoll_event event;
2826
2827 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2828 event.data.ptr = connection;
2829 if (0 != epoll_ctl (daemon->epoll_fd,
2830 EPOLL_CTL_ADD,
2831 connection->socket_fd,
2832 &event))
2833 {
2834 eno = errno;
2835#ifdef HAVE_MESSAGES
2836 MHD_DLOG (daemon,
2837 _ ("Call to epoll_ctl failed: %s\n"),
2838 MHD_socket_last_strerr_ ());
2839#endif
2840 }
2841 else
2842 { /* 'socket_fd' has been added to 'epool' */
2843 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2844
2845 return MHD_YES; /* *** Function success exit point *** */
2846 }
2847 }
2848 else
2849 {
2850 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
2851 | MHD_EPOLL_STATE_WRITE_READY
2852 | MHD_EPOLL_STATE_IN_EREADY_EDLL;
2853 EDLL_insert (daemon->eready_head,
2854 daemon->eready_tail,
2855 connection);
2830 2856
2831 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET; 2857 return MHD_YES; /* *** Function success exit point *** */
2832 event.data.ptr = connection; 2858 }
2833 if (0 != epoll_ctl (daemon->epoll_fd, 2859 }
2834 EPOLL_CTL_ADD, 2860 else /* No 'epoll' */
2835 connection->socket_fd, 2861#endif /* EPOLL_SUPPORT */
2836 &event)) 2862 return MHD_YES; /* *** Function success exit point *** */
2863 }
2864
2865 /* ** Below is a cleanup path ** */
2866 if (NULL != daemon->notify_connection)
2867 daemon->notify_connection (daemon->notify_connection_cls,
2868 connection,
2869 &connection->socket_context,
2870 MHD_CONNECTION_NOTIFY_CLOSED);
2871 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2872 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2837 { 2873 {
2838 eno = errno; 2874 XDLL_remove (daemon->normal_timeout_head,
2839#ifdef HAVE_MESSAGES 2875 daemon->normal_timeout_tail,
2840 MHD_DLOG (daemon, 2876 connection);
2841 _ ("Call to epoll_ctl failed: %s\n"),
2842 MHD_socket_last_strerr_ ());
2843#endif
2844 goto cleanup;
2845 } 2877 }
2846 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET; 2878 DLL_remove (daemon->connections_head,
2847 } 2879 daemon->connections_tail,
2848 else 2880 connection);
2849 { 2881 daemon->connections--;
2850 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY 2882 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2851 | MHD_EPOLL_STATE_WRITE_READY
2852 | MHD_EPOLL_STATE_IN_EREADY_EDLL;
2853 EDLL_insert (daemon->eready_head,
2854 daemon->eready_tail,
2855 connection);
2856 } 2883 }
2884 MHD_pool_destroy (connection->pool);
2857 } 2885 }
2858#endif 2886 /* Free resources allocated before the call of this functions */
2859
2860 return MHD_YES;
2861
2862cleanup:
2863 if (NULL != daemon->notify_connection)
2864 daemon->notify_connection (daemon->notify_connection_cls,
2865 connection,
2866 &connection->socket_context,
2867 MHD_CONNECTION_NOTIFY_CLOSED);
2868#ifdef HTTPS_SUPPORT 2887#ifdef HTTPS_SUPPORT
2869 if (NULL != connection->tls_session) 2888 if (NULL != connection->tls_session)
2870 gnutls_deinit (connection->tls_session); 2889 gnutls_deinit (connection->tls_session);
2871#endif /* HTTPS_SUPPORT */ 2890#endif /* HTTPS_SUPPORT */
2872 MHD_socket_close_chk_ (connection->socket_fd);
2873 MHD_ip_limit_del (daemon, 2891 MHD_ip_limit_del (daemon,
2874 connection->addr, 2892 connection->addr,
2875 connection->addr_len); 2893 connection->addr_len);
2876#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2877 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2878#endif
2879 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2880 {
2881 XDLL_remove (daemon->normal_timeout_head,
2882 daemon->normal_timeout_tail,
2883 connection);
2884 }
2885 DLL_remove (daemon->connections_head,
2886 daemon->connections_tail,
2887 connection);
2888#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2889 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2890#endif
2891 MHD_pool_destroy (connection->pool);
2892 free (connection->addr); 2894 free (connection->addr);
2895 MHD_socket_close_chk_ (connection->socket_fd);
2893 free (connection); 2896 free (connection);
2894 if (0 != eno) 2897 if (0 != eno)
2895 errno = eno; 2898 errno = eno;
2899#ifdef EINVAL
2896 else 2900 else
2897 errno = EINVAL; 2901 errno = EINVAL;
2898 return MHD_NO; 2902#endif /* EINVAL */
2903 return MHD_NO; /* *** Function failure exit point *** */
2899} 2904}
2900 2905
2901 2906