diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 257 |
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 | |||
2862 | cleanup: | ||
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 | ||