diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 392 |
1 files changed, 303 insertions, 89 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index a25fe358..2fb87ed4 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -626,11 +626,15 @@ MHD_get_fdset (struct MHD_Daemon *daemon, | |||
626 | fd_set *except_fd_set, | 626 | fd_set *except_fd_set, |
627 | MHD_socket *max_fd) | 627 | MHD_socket *max_fd) |
628 | { | 628 | { |
629 | return MHD_get_fdset2(daemon, read_fd_set, | 629 | return MHD_get_fdset2 (daemon, |
630 | write_fd_set, except_fd_set, | 630 | read_fd_set, |
631 | max_fd, _MHD_SYS_DEFAULT_FD_SETSIZE); | 631 | write_fd_set, |
632 | except_fd_set, | ||
633 | max_fd, | ||
634 | _MHD_SYS_DEFAULT_FD_SETSIZE); | ||
632 | } | 635 | } |
633 | 636 | ||
637 | |||
634 | /** | 638 | /** |
635 | * Obtain the `select()` sets for this daemon. | 639 | * Obtain the `select()` sets for this daemon. |
636 | * Daemon's FDs will be added to fd_sets. To get only | 640 | * Daemon's FDs will be added to fd_sets. To get only |
@@ -729,25 +733,25 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon, | |||
729 | } | 733 | } |
730 | for (urh = daemon->urh_head; NULL != urh; urh = urh->next) | 734 | for (urh = daemon->urh_head; NULL != urh; urh = urh->next) |
731 | { | 735 | { |
732 | if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) && | 736 | if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) && |
733 | (! MHD_add_to_fd_set_ (urh->mhd_socket, | 737 | (! MHD_add_to_fd_set_ (urh->mhd.socket, |
734 | read_fd_set, | 738 | read_fd_set, |
735 | max_fd, | 739 | max_fd, |
736 | fd_setsize)) ) | 740 | fd_setsize)) ) |
737 | result = MHD_NO; | 741 | result = MHD_NO; |
738 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) && | 742 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) && |
739 | (! MHD_add_to_fd_set_ (urh->mhd_socket, | 743 | (! MHD_add_to_fd_set_ (urh->mhd.socket, |
740 | write_fd_set, | 744 | write_fd_set, |
741 | max_fd, | 745 | max_fd, |
742 | fd_setsize)) ) | 746 | fd_setsize)) ) |
743 | result = MHD_NO; | 747 | result = MHD_NO; |
744 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) && | 748 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) && |
745 | (! MHD_add_to_fd_set_ (urh->connection->socket_fd, | 749 | (! MHD_add_to_fd_set_ (urh->connection->socket_fd, |
746 | read_fd_set, | 750 | read_fd_set, |
747 | max_fd, | 751 | max_fd, |
748 | fd_setsize)) ) | 752 | fd_setsize)) ) |
749 | result = MHD_NO; | 753 | result = MHD_NO; |
750 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) && | 754 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && |
751 | (! MHD_add_to_fd_set_ (urh->connection->socket_fd, | 755 | (! MHD_add_to_fd_set_ (urh->connection->socket_fd, |
752 | write_fd_set, | 756 | write_fd_set, |
753 | max_fd, | 757 | max_fd, |
@@ -2175,7 +2179,7 @@ static void | |||
2175 | process_urh (struct MHD_UpgradeResponseHandle *urh) | 2179 | process_urh (struct MHD_UpgradeResponseHandle *urh) |
2176 | { | 2180 | { |
2177 | /* handle reading from TLS client and writing to application */ | 2181 | /* handle reading from TLS client and writing to application */ |
2178 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) && | 2182 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) && |
2179 | (urh->in_buffer_off < urh->in_buffer_size) ) | 2183 | (urh->in_buffer_off < urh->in_buffer_size) ) |
2180 | { | 2184 | { |
2181 | ssize_t res; | 2185 | ssize_t res; |
@@ -2186,25 +2190,25 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) | |||
2186 | if ( (GNUTLS_E_AGAIN == res) || | 2190 | if ( (GNUTLS_E_AGAIN == res) || |
2187 | (GNUTLS_E_INTERRUPTED == res) ) | 2191 | (GNUTLS_E_INTERRUPTED == res) ) |
2188 | { | 2192 | { |
2189 | urh->celi_client &= ~MHD_EPOLL_STATE_READ_READY; | 2193 | urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY; |
2190 | } | 2194 | } |
2191 | else if (res > 0) | 2195 | else if (res > 0) |
2192 | { | 2196 | { |
2193 | urh->in_buffer_off += res; | 2197 | urh->in_buffer_off += res; |
2194 | } | 2198 | } |
2195 | } | 2199 | } |
2196 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) && | 2200 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) && |
2197 | (urh->in_buffer_off > 0) ) | 2201 | (urh->in_buffer_off > 0) ) |
2198 | { | 2202 | { |
2199 | size_t res; | 2203 | size_t res; |
2200 | 2204 | ||
2201 | res = write (urh->mhd_socket, | 2205 | res = write (urh->mhd.socket, |
2202 | urh->in_buffer, | 2206 | urh->in_buffer, |
2203 | urh->in_buffer_off); | 2207 | urh->in_buffer_off); |
2204 | if (-1 == res) | 2208 | if (-1 == res) |
2205 | { | 2209 | { |
2206 | /* FIXME: differenciate by errno? */ | 2210 | /* FIXME: differenciate by errno? */ |
2207 | urh->celi_mhd &= ~MHD_EPOLL_STATE_WRITE_READY; | 2211 | urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY; |
2208 | } | 2212 | } |
2209 | else | 2213 | else |
2210 | { | 2214 | { |
@@ -2223,25 +2227,25 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) | |||
2223 | } | 2227 | } |
2224 | 2228 | ||
2225 | /* handle reading from application and writing to HTTPS client */ | 2229 | /* handle reading from application and writing to HTTPS client */ |
2226 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) && | 2230 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) && |
2227 | (urh->out_buffer_off < urh->out_buffer_size) ) | 2231 | (urh->out_buffer_off < urh->out_buffer_size) ) |
2228 | { | 2232 | { |
2229 | size_t res; | 2233 | size_t res; |
2230 | 2234 | ||
2231 | res = read (urh->mhd_socket, | 2235 | res = read (urh->mhd.socket, |
2232 | &urh->out_buffer[urh->out_buffer_off], | 2236 | &urh->out_buffer[urh->out_buffer_off], |
2233 | urh->out_buffer_size - urh->out_buffer_off); | 2237 | urh->out_buffer_size - urh->out_buffer_off); |
2234 | if (-1 == res) | 2238 | if (-1 == res) |
2235 | { | 2239 | { |
2236 | /* FIXME: differenciate by errno? */ | 2240 | /* FIXME: differenciate by errno? */ |
2237 | urh->celi_mhd &= ~MHD_EPOLL_STATE_READ_READY; | 2241 | urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; |
2238 | } | 2242 | } |
2239 | else | 2243 | else |
2240 | { | 2244 | { |
2241 | urh->out_buffer_off += res; | 2245 | urh->out_buffer_off += res; |
2242 | } | 2246 | } |
2243 | } | 2247 | } |
2244 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) && | 2248 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && |
2245 | (urh->out_buffer_off > 0) ) | 2249 | (urh->out_buffer_off > 0) ) |
2246 | { | 2250 | { |
2247 | ssize_t res; | 2251 | ssize_t res; |
@@ -2252,7 +2256,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) | |||
2252 | if ( (GNUTLS_E_AGAIN == res) || | 2256 | if ( (GNUTLS_E_AGAIN == res) || |
2253 | (GNUTLS_E_INTERRUPTED == res) ) | 2257 | (GNUTLS_E_INTERRUPTED == res) ) |
2254 | { | 2258 | { |
2255 | urh->celi_client &= ~MHD_EPOLL_STATE_WRITE_READY; | 2259 | urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY; |
2256 | } | 2260 | } |
2257 | else if (res > 0) | 2261 | else if (res > 0) |
2258 | { | 2262 | { |
@@ -2359,13 +2363,13 @@ MHD_run_from_select (struct MHD_Daemon *daemon, | |||
2359 | { | 2363 | { |
2360 | /* update urh state based on select() output */ | 2364 | /* update urh state based on select() output */ |
2361 | if (FD_ISSET (urh->connection->socket_fd, read_fd_set)) | 2365 | if (FD_ISSET (urh->connection->socket_fd, read_fd_set)) |
2362 | urh->celi_client |= MHD_EPOLL_STATE_READ_READY; | 2366 | urh->app.celi |= MHD_EPOLL_STATE_READ_READY; |
2363 | if (FD_ISSET (urh->connection->socket_fd, write_fd_set)) | 2367 | if (FD_ISSET (urh->connection->socket_fd, write_fd_set)) |
2364 | urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY; | 2368 | urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY; |
2365 | if (FD_ISSET (urh->mhd_socket, read_fd_set)) | 2369 | if (FD_ISSET (urh->mhd.socket, read_fd_set)) |
2366 | urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY; | 2370 | urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY; |
2367 | if (FD_ISSET (urh->mhd_socket, write_fd_set)) | 2371 | if (FD_ISSET (urh->mhd.socket, write_fd_set)) |
2368 | urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY; | 2372 | urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY; |
2369 | /* call generic forwarding function for passing data */ | 2373 | /* call generic forwarding function for passing data */ |
2370 | process_urh (urh); | 2374 | process_urh (urh); |
2371 | } | 2375 | } |
@@ -2632,15 +2636,15 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
2632 | for (urh = daemon->urh_head; NULL != urh; urh = urh->next) | 2636 | for (urh = daemon->urh_head; NULL != urh; urh = urh->next) |
2633 | { | 2637 | { |
2634 | p[poll_server+i].fd = urh->connection->socket_fd; | 2638 | p[poll_server+i].fd = urh->connection->socket_fd; |
2635 | if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) | 2639 | if (0 == (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) |
2636 | p[poll_server+i].events |= POLLIN; | 2640 | p[poll_server+i].events |= POLLIN; |
2637 | if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) | 2641 | if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) |
2638 | p[poll_server+i].events |= POLLOUT; | 2642 | p[poll_server+i].events |= POLLOUT; |
2639 | i++; | 2643 | i++; |
2640 | p[poll_server+i].fd = urh->mhd_socket; | 2644 | p[poll_server+i].fd = urh->mhd.socket; |
2641 | if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) | 2645 | if (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) |
2642 | p[poll_server+i].events |= POLLIN; | 2646 | p[poll_server+i].events |= POLLIN; |
2643 | if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) | 2647 | if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) |
2644 | p[poll_server+i].events |= POLLOUT; | 2648 | p[poll_server+i].events |= POLLOUT; |
2645 | i++; | 2649 | i++; |
2646 | } | 2650 | } |
@@ -2701,11 +2705,11 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
2701 | if (p[poll_server+i].fd != urh->connection->socket_fd) | 2705 | if (p[poll_server+i].fd != urh->connection->socket_fd) |
2702 | continue; /* fd mismatch, something else happened, retry later ... */ | 2706 | continue; /* fd mismatch, something else happened, retry later ... */ |
2703 | if (0 != (p[poll_server+i].revents & POLLIN)) | 2707 | if (0 != (p[poll_server+i].revents & POLLIN)) |
2704 | urh->celi_client |= MHD_EPOLL_STATE_READ_READY; | 2708 | urh->app.celi |= MHD_EPOLL_STATE_READ_READY; |
2705 | if (0 != (p[poll_server+i].revents & POLLOUT)) | 2709 | if (0 != (p[poll_server+i].revents & POLLOUT)) |
2706 | urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY; | 2710 | urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY; |
2707 | i++; | 2711 | i++; |
2708 | if (p[poll_server+i].fd != urh->mhd_socket) | 2712 | if (p[poll_server+i].fd != urh->mhd.socket) |
2709 | { | 2713 | { |
2710 | /* fd mismatch, something else happened, retry later ... */ | 2714 | /* fd mismatch, something else happened, retry later ... */ |
2711 | /* may still be able to do something based on updates | 2715 | /* may still be able to do something based on updates |
@@ -2714,9 +2718,9 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
2714 | continue; | 2718 | continue; |
2715 | } | 2719 | } |
2716 | if (0 != (p[poll_server+i].revents & POLLIN)) | 2720 | if (0 != (p[poll_server+i].revents & POLLIN)) |
2717 | urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY; | 2721 | urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY; |
2718 | if (0 != (p[poll_server+i].revents & POLLOUT)) | 2722 | if (0 != (p[poll_server+i].revents & POLLOUT)) |
2719 | urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY; | 2723 | urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY; |
2720 | i++; | 2724 | i++; |
2721 | process_urh (urh); | 2725 | process_urh (urh); |
2722 | } | 2726 | } |
@@ -2832,6 +2836,136 @@ MHD_poll (struct MHD_Daemon *daemon, | |||
2832 | #define MAX_EVENTS 128 | 2836 | #define MAX_EVENTS 128 |
2833 | 2837 | ||
2834 | 2838 | ||
2839 | #if HTTPS_SUPPORT | ||
2840 | |||
2841 | /** | ||
2842 | * Do epoll()-based processing for TLS connections that have been | ||
2843 | * upgraded. This requires a separate epoll() invocation as we | ||
2844 | * cannot use the `struct MHD_Connection` data structures for | ||
2845 | * the `union epoll_data` in this case. | ||
2846 | */ | ||
2847 | static int | ||
2848 | run_epoll_for_upgrade (struct MHD_Daemon *daemon) | ||
2849 | { | ||
2850 | struct epoll_event events[MAX_EVENTS]; | ||
2851 | int num_events; | ||
2852 | unsigned int i; | ||
2853 | |||
2854 | num_events = MAX_EVENTS; | ||
2855 | while (MAX_EVENTS == num_events) | ||
2856 | { | ||
2857 | /* update event masks */ | ||
2858 | num_events = epoll_wait (daemon->epoll_upgrade_fd, | ||
2859 | events, | ||
2860 | MAX_EVENTS, | ||
2861 | 0); | ||
2862 | if (-1 == num_events) | ||
2863 | { | ||
2864 | const int err = MHD_socket_get_error_ (); | ||
2865 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
2866 | return MHD_YES; | ||
2867 | #ifdef HAVE_MESSAGES | ||
2868 | MHD_DLOG (daemon, | ||
2869 | "Call to epoll_wait failed: %s\n", | ||
2870 | MHD_socket_strerr_ (err)); | ||
2871 | #endif | ||
2872 | return MHD_NO; | ||
2873 | } | ||
2874 | for (i=0;i<(unsigned int) num_events;i++) | ||
2875 | { | ||
2876 | struct UpgradeEpollHandle *ueh = events[i].data.ptr; | ||
2877 | struct MHD_UpgradeResponseHandle *urh = ueh->urh; | ||
2878 | struct epoll_event event; | ||
2879 | int fd; | ||
2880 | |||
2881 | /* Update our state based on what is ready according to epoll() */ | ||
2882 | if (0 != (events[i].events & EPOLLIN)) | ||
2883 | ueh->celi |= MHD_EPOLL_STATE_READ_READY; | ||
2884 | if (0 != (events[i].events & EPOLLOUT)) | ||
2885 | ueh->celi |= MHD_EPOLL_STATE_WRITE_READY; | ||
2886 | |||
2887 | /* shuffle data based on buffers and FD readyness */ | ||
2888 | process_urh (urh); | ||
2889 | |||
2890 | /* if we drained the IO buffer, re-add to epoll() to wait for more! */ | ||
2891 | if (0 == (ueh->celi & MHD_EPOLL_STATE_READ_READY)) | ||
2892 | { | ||
2893 | event.events = EPOLLIN; | ||
2894 | event.data.ptr = ueh; | ||
2895 | fd = (ueh == &urh->mhd) ? ueh->socket : urh->connection->socket_fd; | ||
2896 | if (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
2897 | EPOLL_CTL_ADD, | ||
2898 | fd, | ||
2899 | &event)) | ||
2900 | { | ||
2901 | MHD_socket myfd; | ||
2902 | |||
2903 | /* Handle error by closing OUR socket; with some | ||
2904 | luck, this should tricker the application to fail | ||
2905 | to read, and then the application should close | ||
2906 | the connection completely. */ | ||
2907 | |||
2908 | /* epoll documentation suggests that closing a FD | ||
2909 | automatically removes it from the epoll set; | ||
2910 | however, this is not true as if we fail to do | ||
2911 | manually remove it, we are still seeing an event | ||
2912 | for this fd in epoll, causing grief | ||
2913 | (use-after-free...) --- at least on my system. */ | ||
2914 | myfd = urh->mhd.socket; | ||
2915 | if ( (fd != myfd) && | ||
2916 | (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
2917 | EPOLL_CTL_DEL, | ||
2918 | urh->mhd.socket, | ||
2919 | NULL)) ) | ||
2920 | MHD_PANIC ("Failed to remove FD from epoll set\n"); | ||
2921 | urh->mhd.socket = MHD_INVALID_SOCKET; | ||
2922 | MHD_socket_close_ (myfd); | ||
2923 | continue; | ||
2924 | } | ||
2925 | } | ||
2926 | if (0 == (ueh->celi & MHD_EPOLL_STATE_WRITE_READY)) | ||
2927 | { | ||
2928 | event.events = EPOLLOUT; | ||
2929 | event.data.ptr = ueh; | ||
2930 | fd = (ueh == &ueh->urh->mhd) ? ueh->socket : ueh->urh->connection->socket_fd; | ||
2931 | if (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
2932 | EPOLL_CTL_ADD, | ||
2933 | fd, | ||
2934 | &event)) | ||
2935 | { | ||
2936 | MHD_socket myfd; | ||
2937 | |||
2938 | /* Handle error by closing OUR socket; with some | ||
2939 | luck, this should tricker the application to fail | ||
2940 | to read, and then the application should close | ||
2941 | the connection completely. */ | ||
2942 | |||
2943 | /* epoll documentation suggests that closing a FD | ||
2944 | automatically removes it from the epoll set; | ||
2945 | however, this is not true as if we fail to do | ||
2946 | manually remove it, we are still seeing an event | ||
2947 | for this fd in epoll, causing grief | ||
2948 | (use-after-free...) --- at least on my system. */ | ||
2949 | myfd = urh->mhd.socket; | ||
2950 | if ( (fd != myfd) && | ||
2951 | (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
2952 | EPOLL_CTL_DEL, | ||
2953 | urh->mhd.socket, | ||
2954 | NULL)) ) | ||
2955 | MHD_PANIC ("Failed to remove FD from epoll set\n"); | ||
2956 | |||
2957 | urh->mhd.socket = MHD_INVALID_SOCKET; | ||
2958 | MHD_socket_close_ (myfd); | ||
2959 | continue; | ||
2960 | } | ||
2961 | } | ||
2962 | } | ||
2963 | } | ||
2964 | return MHD_YES; | ||
2965 | } | ||
2966 | #endif | ||
2967 | |||
2968 | |||
2835 | /** | 2969 | /** |
2836 | * Do epoll()-based processing (this function is allowed to | 2970 | * Do epoll()-based processing (this function is allowed to |
2837 | * block if @a may_block is set to #MHD_YES). | 2971 | * block if @a may_block is set to #MHD_YES). |
@@ -2844,6 +2978,9 @@ static int | |||
2844 | MHD_epoll (struct MHD_Daemon *daemon, | 2978 | MHD_epoll (struct MHD_Daemon *daemon, |
2845 | int may_block) | 2979 | int may_block) |
2846 | { | 2980 | { |
2981 | #if HTTPS_SUPPORT | ||
2982 | static const char *upgrade_marker = "upgrade_ptr"; | ||
2983 | #endif | ||
2847 | struct MHD_Connection *pos; | 2984 | struct MHD_Connection *pos; |
2848 | struct MHD_Connection *next; | 2985 | struct MHD_Connection *next; |
2849 | struct epoll_event events[MAX_EVENTS]; | 2986 | struct epoll_event events[MAX_EVENTS]; |
@@ -2879,6 +3016,27 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2879 | } | 3016 | } |
2880 | daemon->listen_socket_in_epoll = MHD_YES; | 3017 | daemon->listen_socket_in_epoll = MHD_YES; |
2881 | } | 3018 | } |
3019 | #if HTTPS_SUPPORT | ||
3020 | if ( (MHD_NO == daemon->upgrade_fd_in_epoll) && | ||
3021 | (MHD_INVALID_SOCKET != daemon->epoll_upgrade_fd) ) | ||
3022 | { | ||
3023 | event.events = EPOLLIN | EPOLLOUT; | ||
3024 | event.data.ptr = (void *) upgrade_marker; | ||
3025 | if (0 != epoll_ctl (daemon->epoll_fd, | ||
3026 | EPOLL_CTL_ADD, | ||
3027 | daemon->epoll_upgrade_fd, | ||
3028 | &event)) | ||
3029 | { | ||
3030 | #ifdef HAVE_MESSAGES | ||
3031 | MHD_DLOG (daemon, | ||
3032 | "Call to epoll_ctl failed: %s\n", | ||
3033 | MHD_socket_last_strerr_ ()); | ||
3034 | #endif | ||
3035 | return MHD_NO; | ||
3036 | } | ||
3037 | daemon->upgrade_fd_in_epoll = MHD_YES; | ||
3038 | } | ||
3039 | #endif | ||
2882 | if ( ( (MHD_YES == daemon->listen_socket_in_epoll) && | 3040 | if ( ( (MHD_YES == daemon->listen_socket_in_epoll) && |
2883 | (daemon->connections == daemon->connection_limit) ) || | 3041 | (daemon->connections == daemon->connection_limit) ) || |
2884 | (MHD_YES == daemon->at_limit) ) | 3042 | (MHD_YES == daemon->at_limit) ) |
@@ -2917,7 +3075,9 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2917 | { | 3075 | { |
2918 | /* update event masks */ | 3076 | /* update event masks */ |
2919 | num_events = epoll_wait (daemon->epoll_fd, | 3077 | num_events = epoll_wait (daemon->epoll_fd, |
2920 | events, MAX_EVENTS, timeout_ms); | 3078 | events, |
3079 | MAX_EVENTS, | ||
3080 | timeout_ms); | ||
2921 | if (-1 == num_events) | 3081 | if (-1 == num_events) |
2922 | { | 3082 | { |
2923 | const int err = MHD_socket_get_error_ (); | 3083 | const int err = MHD_socket_get_error_ (); |
@@ -2932,8 +3092,25 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2932 | } | 3092 | } |
2933 | for (i=0;i<(unsigned int) num_events;i++) | 3093 | for (i=0;i<(unsigned int) num_events;i++) |
2934 | { | 3094 | { |
3095 | /* First, check for the values of `ptr` that would indicate | ||
3096 | that this event is not about a normal connection. */ | ||
2935 | if (NULL == events[i].data.ptr) | 3097 | if (NULL == events[i].data.ptr) |
2936 | continue; /* shutdown signal! */ | 3098 | continue; /* shutdown signal! */ |
3099 | #if HTTPS_SUPPORT | ||
3100 | if (upgrade_marker == events[i].data.ptr) | ||
3101 | { | ||
3102 | /* activity on an upgraded connection, we process | ||
3103 | those in a separate epoll() */ | ||
3104 | daemon->upgrade_fd_in_epoll = MHD_NO; | ||
3105 | run_epoll_for_upgrade (daemon); | ||
3106 | continue; | ||
3107 | } | ||
3108 | #endif | ||
3109 | /* UGH: we're storing pointers and fds in the same union | ||
3110 | here; incredibly ugly and somewhat risky, even though a | ||
3111 | pointer with the same numeric value as the wpipe[0] can | ||
3112 | be expected to be rare... FIXME (a construction similar | ||
3113 | to what we did with the `upgrade_marker` should do) */ | ||
2937 | if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && | 3114 | if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && |
2938 | (daemon->wpipe[0] == events[i].data.fd) ) | 3115 | (daemon->wpipe[0] == events[i].data.fd) ) |
2939 | { | 3116 | { |
@@ -2942,39 +3119,7 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2942 | MHD_pipe_drain_ (daemon->wpipe[0]); | 3119 | MHD_pipe_drain_ (daemon->wpipe[0]); |
2943 | continue; | 3120 | continue; |
2944 | } | 3121 | } |
2945 | if (daemon != events[i].data.ptr) | 3122 | if (daemon == events[i].data.ptr) |
2946 | { | ||
2947 | /* this is an event relating to a 'normal' connection, | ||
2948 | remember the event and if appropriate mark the | ||
2949 | connection as 'eready'. */ | ||
2950 | pos = events[i].data.ptr; | ||
2951 | if (0 != (events[i].events & EPOLLIN)) | ||
2952 | { | ||
2953 | pos->epoll_state |= MHD_EPOLL_STATE_READ_READY; | ||
2954 | if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) || | ||
2955 | (pos->read_buffer_size > pos->read_buffer_offset) ) && | ||
2956 | (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) ) | ||
2957 | { | ||
2958 | EDLL_insert (daemon->eready_head, | ||
2959 | daemon->eready_tail, | ||
2960 | pos); | ||
2961 | pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
2962 | } | ||
2963 | } | ||
2964 | if (0 != (events[i].events & EPOLLOUT)) | ||
2965 | { | ||
2966 | pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY; | ||
2967 | if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) && | ||
2968 | (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) ) | ||
2969 | { | ||
2970 | EDLL_insert (daemon->eready_head, | ||
2971 | daemon->eready_tail, | ||
2972 | pos); | ||
2973 | pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
2974 | } | ||
2975 | } | ||
2976 | } | ||
2977 | else /* must be listen socket */ | ||
2978 | { | 3123 | { |
2979 | /* run 'accept' until it fails or we are not allowed to take | 3124 | /* run 'accept' until it fails or we are not allowed to take |
2980 | on more connections */ | 3125 | on more connections */ |
@@ -2984,8 +3129,39 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2984 | (series_length < 128) && | 3129 | (series_length < 128) && |
2985 | (MHD_NO == daemon->at_limit) ) | 3130 | (MHD_NO == daemon->at_limit) ) |
2986 | series_length++; | 3131 | series_length++; |
3132 | continue; | ||
2987 | } | 3133 | } |
2988 | } | 3134 | /* this is an event relating to a 'normal' connection, |
3135 | remember the event and if appropriate mark the | ||
3136 | connection as 'eready'. */ | ||
3137 | pos = events[i].data.ptr; | ||
3138 | /* normal processing: update read/write data */ | ||
3139 | if (0 != (events[i].events & EPOLLIN)) | ||
3140 | { | ||
3141 | pos->epoll_state |= MHD_EPOLL_STATE_READ_READY; | ||
3142 | if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) || | ||
3143 | (pos->read_buffer_size > pos->read_buffer_offset) ) && | ||
3144 | (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) ) | ||
3145 | { | ||
3146 | EDLL_insert (daemon->eready_head, | ||
3147 | daemon->eready_tail, | ||
3148 | pos); | ||
3149 | pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
3150 | } | ||
3151 | } | ||
3152 | if (0 != (events[i].events & EPOLLOUT)) | ||
3153 | { | ||
3154 | pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY; | ||
3155 | if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) && | ||
3156 | (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) ) | ||
3157 | { | ||
3158 | EDLL_insert (daemon->eready_head, | ||
3159 | daemon->eready_tail, | ||
3160 | pos); | ||
3161 | pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
3162 | } | ||
3163 | } | ||
3164 | } | ||
2989 | } | 3165 | } |
2990 | 3166 | ||
2991 | /* we handle resumes here because we may have ready connections | 3167 | /* we handle resumes here because we may have ready connections |
@@ -3426,8 +3602,8 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
3426 | if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0) | 3602 | if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0) |
3427 | { | 3603 | { |
3428 | #ifdef HAVE_MESSAGES | 3604 | #ifdef HAVE_MESSAGES |
3429 | MHD_DLOG(daemon, | 3605 | MHD_DLOG (daemon, |
3430 | "Error initializing DH parameters\n"); | 3606 | "Error initializing DH parameters\n"); |
3431 | #endif | 3607 | #endif |
3432 | return MHD_NO; | 3608 | return MHD_NO; |
3433 | } | 3609 | } |
@@ -3437,8 +3613,8 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
3437 | GNUTLS_X509_FMT_PEM) < 0) | 3613 | GNUTLS_X509_FMT_PEM) < 0) |
3438 | { | 3614 | { |
3439 | #ifdef HAVE_MESSAGES | 3615 | #ifdef HAVE_MESSAGES |
3440 | MHD_DLOG(daemon, | 3616 | MHD_DLOG (daemon, |
3441 | "Bad Diffie-Hellman parameters format\n"); | 3617 | "Bad Diffie-Hellman parameters format\n"); |
3442 | #endif | 3618 | #endif |
3443 | gnutls_dh_params_deinit (daemon->https_mem_dhparams); | 3619 | gnutls_dh_params_deinit (daemon->https_mem_dhparams); |
3444 | return MHD_NO; | 3620 | return MHD_NO; |
@@ -3652,34 +3828,27 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
3652 | 3828 | ||
3653 | 3829 | ||
3654 | #ifdef EPOLL_SUPPORT | 3830 | #ifdef EPOLL_SUPPORT |
3655 | /** | ||
3656 | * Setup epoll() FD for the daemon and initialize it to listen | ||
3657 | * on the listen FD. | ||
3658 | * | ||
3659 | * @param daemon daemon to initialize for epoll() | ||
3660 | * @return #MHD_YES on success, #MHD_NO on failure | ||
3661 | */ | ||
3662 | static int | 3831 | static int |
3663 | setup_epoll_to_listen (struct MHD_Daemon *daemon) | 3832 | setup_epoll_fd (struct MHD_Daemon *daemon) |
3664 | { | 3833 | { |
3665 | struct epoll_event event; | 3834 | int fd; |
3666 | 3835 | ||
3667 | #ifdef USE_EPOLL_CREATE1 | 3836 | #ifdef USE_EPOLL_CREATE1 |
3668 | daemon->epoll_fd = epoll_create1 (EPOLL_CLOEXEC); | 3837 | fd = epoll_create1 (EPOLL_CLOEXEC); |
3669 | #else /* ! USE_EPOLL_CREATE1 */ | 3838 | #else /* ! USE_EPOLL_CREATE1 */ |
3670 | daemon->epoll_fd = epoll_create (MAX_EVENTS); | 3839 | fd = epoll_create (MAX_EVENTS); |
3671 | #endif /* ! USE_EPOLL_CREATE1 */ | 3840 | #endif /* ! USE_EPOLL_CREATE1 */ |
3672 | if (-1 == daemon->epoll_fd) | 3841 | if (MHD_INVALID_SOCKET == fd) |
3673 | { | 3842 | { |
3674 | #ifdef HAVE_MESSAGES | 3843 | #ifdef HAVE_MESSAGES |
3675 | MHD_DLOG (daemon, | 3844 | MHD_DLOG (daemon, |
3676 | "Call to epoll_create1 failed: %s\n", | 3845 | "Call to epoll_create1 failed: %s\n", |
3677 | MHD_socket_last_strerr_ ()); | 3846 | MHD_socket_last_strerr_ ()); |
3678 | #endif | 3847 | #endif |
3679 | return MHD_NO; | 3848 | return MHD_INVALID_SOCKET; |
3680 | } | 3849 | } |
3681 | #if !defined(USE_EPOLL_CREATE1) | 3850 | #if !defined(USE_EPOLL_CREATE1) |
3682 | if (!MHD_socket_noninheritable_ (daemon->epoll_fd)) | 3851 | if (! MHD_socket_noninheritable_ (fd)) |
3683 | { | 3852 | { |
3684 | #ifdef HAVE_MESSAGES | 3853 | #ifdef HAVE_MESSAGES |
3685 | MHD_DLOG (daemon, | 3854 | MHD_DLOG (daemon, |
@@ -3687,6 +3856,33 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) | |||
3687 | #endif | 3856 | #endif |
3688 | } | 3857 | } |
3689 | #endif /* ! USE_EPOLL_CREATE1 */ | 3858 | #endif /* ! USE_EPOLL_CREATE1 */ |
3859 | return fd; | ||
3860 | } | ||
3861 | |||
3862 | |||
3863 | /** | ||
3864 | * Setup epoll() FD for the daemon and initialize it to listen | ||
3865 | * on the listen FD. | ||
3866 | * | ||
3867 | * @param daemon daemon to initialize for epoll() | ||
3868 | * @return #MHD_YES on success, #MHD_NO on failure | ||
3869 | */ | ||
3870 | static int | ||
3871 | setup_epoll_to_listen (struct MHD_Daemon *daemon) | ||
3872 | { | ||
3873 | struct epoll_event event; | ||
3874 | |||
3875 | daemon->epoll_fd = setup_epoll_fd (daemon); | ||
3876 | if (MHD_INVALID_SOCKET == daemon->epoll_fd) | ||
3877 | return MHD_NO; | ||
3878 | #if HTTPS_SUPPORT | ||
3879 | if (MHD_USE_TLS_EPOLL_UPGRADE == (MHD_USE_TLS_EPOLL_UPGRADE & daemon->options)) | ||
3880 | { | ||
3881 | daemon->epoll_upgrade_fd = setup_epoll_fd (daemon); | ||
3882 | if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd) | ||
3883 | return MHD_NO; | ||
3884 | } | ||
3885 | #endif | ||
3690 | if (MHD_INVALID_SOCKET == daemon->socket_fd) | 3886 | if (MHD_INVALID_SOCKET == daemon->socket_fd) |
3691 | return MHD_YES; /* non-listening daemon */ | 3887 | return MHD_YES; /* non-listening daemon */ |
3692 | event.events = EPOLLIN; | 3888 | event.events = EPOLLIN; |
@@ -3788,6 +3984,9 @@ MHD_start_daemon_va (unsigned int flags, | |||
3788 | memset (daemon, 0, sizeof (struct MHD_Daemon)); | 3984 | memset (daemon, 0, sizeof (struct MHD_Daemon)); |
3789 | #ifdef EPOLL_SUPPORT | 3985 | #ifdef EPOLL_SUPPORT |
3790 | daemon->epoll_fd = -1; | 3986 | daemon->epoll_fd = -1; |
3987 | #if HTTPS_SUPPORT | ||
3988 | daemon->epoll_upgrade_fd = -1; | ||
3989 | #endif | ||
3791 | #endif | 3990 | #endif |
3792 | /* try to open listen socket */ | 3991 | /* try to open listen socket */ |
3793 | #if HTTPS_SUPPORT | 3992 | #if HTTPS_SUPPORT |
@@ -3842,7 +4041,7 @@ MHD_start_daemon_va (unsigned int flags, | |||
3842 | free (daemon); | 4041 | free (daemon); |
3843 | return NULL; | 4042 | return NULL; |
3844 | } | 4043 | } |
3845 | if (!MHD_itc_nonblocking_(daemon->wpipe[0])) | 4044 | if (! MHD_itc_nonblocking_(daemon->wpipe[0])) |
3846 | { | 4045 | { |
3847 | #ifdef HAVE_MESSAGES | 4046 | #ifdef HAVE_MESSAGES |
3848 | MHD_DLOG (daemon, | 4047 | MHD_DLOG (daemon, |
@@ -4482,6 +4681,10 @@ thread_failed: | |||
4482 | #ifdef EPOLL_SUPPORT | 4681 | #ifdef EPOLL_SUPPORT |
4483 | if (-1 != daemon->epoll_fd) | 4682 | if (-1 != daemon->epoll_fd) |
4484 | close (daemon->epoll_fd); | 4683 | close (daemon->epoll_fd); |
4684 | #if HTTPS_SUPPORT | ||
4685 | if (-1 != daemon->epoll_upgrade_fd) | ||
4686 | close (daemon->epoll_upgrade_fd); | ||
4687 | #endif | ||
4485 | #endif | 4688 | #endif |
4486 | #ifdef DAUTH_SUPPORT | 4689 | #ifdef DAUTH_SUPPORT |
4487 | free (daemon->nnc); | 4690 | free (daemon->nnc); |
@@ -4710,6 +4913,11 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
4710 | if ( (-1 != daemon->worker_pool[i].epoll_fd) && | 4913 | if ( (-1 != daemon->worker_pool[i].epoll_fd) && |
4711 | (0 != MHD_socket_close_ (daemon->worker_pool[i].epoll_fd)) ) | 4914 | (0 != MHD_socket_close_ (daemon->worker_pool[i].epoll_fd)) ) |
4712 | MHD_PANIC ("close failed\n"); | 4915 | MHD_PANIC ("close failed\n"); |
4916 | #if HTTPS_SUPPORT | ||
4917 | if ( (-1 != daemon->worker_pool[i].epoll_upgrade_fd) && | ||
4918 | (0 != MHD_socket_close_ (daemon->worker_pool[i].epoll_upgrade_fd)) ) | ||
4919 | MHD_PANIC ("close failed\n"); | ||
4920 | #endif | ||
4713 | #endif | 4921 | #endif |
4714 | /* Individual pipes are always used */ | 4922 | /* Individual pipes are always used */ |
4715 | if (1) | 4923 | if (1) |
@@ -4762,6 +4970,12 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
4762 | (-1 != daemon->epoll_fd) && | 4970 | (-1 != daemon->epoll_fd) && |
4763 | (0 != MHD_socket_close_ (daemon->epoll_fd)) ) | 4971 | (0 != MHD_socket_close_ (daemon->epoll_fd)) ) |
4764 | MHD_PANIC ("close failed\n"); | 4972 | MHD_PANIC ("close failed\n"); |
4973 | #if HTTPS_SUPPORT | ||
4974 | if ( (0 != (daemon->options & MHD_USE_EPOLL)) && | ||
4975 | (-1 != daemon->epoll_upgrade_fd) && | ||
4976 | (0 != MHD_socket_close_ (daemon->epoll_upgrade_fd)) ) | ||
4977 | MHD_PANIC ("close failed\n"); | ||
4978 | #endif | ||
4765 | #endif | 4979 | #endif |
4766 | 4980 | ||
4767 | #ifdef DAUTH_SUPPORT | 4981 | #ifdef DAUTH_SUPPORT |