diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 120 |
1 files changed, 98 insertions, 22 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 03266204..991577b1 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -3252,7 +3252,11 @@ MHD_get_timeout (struct MHD_Daemon *daemon, | |||
3252 | 3252 | ||
3253 | #ifdef EPOLL_SUPPORT | 3253 | #ifdef EPOLL_SUPPORT |
3254 | if ( (0 != (daemon->options & MHD_USE_EPOLL)) && | 3254 | if ( (0 != (daemon->options & MHD_USE_EPOLL)) && |
3255 | (NULL != daemon->eready_head) ) | 3255 | ((NULL != daemon->eready_head) |
3256 | #if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT) | ||
3257 | || (NULL != daemon->eready_urh_head) | ||
3258 | #endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */ | ||
3259 | ) ) | ||
3256 | { | 3260 | { |
3257 | /* Some connection(s) already have some data pending. */ | 3261 | /* Some connection(s) already have some data pending. */ |
3258 | *timeout = 0; | 3262 | *timeout = 0; |
@@ -3972,6 +3976,47 @@ MHD_poll (struct MHD_Daemon *daemon, | |||
3972 | #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) | 3976 | #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) |
3973 | 3977 | ||
3974 | /** | 3978 | /** |
3979 | * Checks whether @a urh has some data to process. | ||
3980 | * | ||
3981 | * @param urh upgrade handler to analyse | ||
3982 | * @return 'true' if @a urh has some data to process, | ||
3983 | * 'false' otherwise | ||
3984 | */ | ||
3985 | static bool | ||
3986 | is_urh_ready(struct MHD_UpgradeResponseHandle * const urh) | ||
3987 | { | ||
3988 | const struct MHD_Connection * const connection = urh->connection; | ||
3989 | |||
3990 | if ( (0 == urh->in_buffer_size) && | ||
3991 | (0 == urh->out_buffer_size) && | ||
3992 | (0 == urh->in_buffer_used) && | ||
3993 | (0 == urh->out_buffer_used) ) | ||
3994 | return false; | ||
3995 | |||
3996 | if (connection->daemon->shutdown) | ||
3997 | return true; | ||
3998 | |||
3999 | if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) || | ||
4000 | (connection->tls_read_ready) ) && | ||
4001 | (urh->in_buffer_used < urh->in_buffer_size) ) | ||
4002 | return true; | ||
4003 | |||
4004 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) && | ||
4005 | (urh->out_buffer_used < urh->out_buffer_size) ) | ||
4006 | return true; | ||
4007 | |||
4008 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && | ||
4009 | (urh->out_buffer_used > 0) ) | ||
4010 | return true; | ||
4011 | |||
4012 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) && | ||
4013 | (urh->in_buffer_used > 0) ) | ||
4014 | return true; | ||
4015 | |||
4016 | return false; | ||
4017 | } | ||
4018 | |||
4019 | /** | ||
3975 | * Do epoll()-based processing for TLS connections that have been | 4020 | * Do epoll()-based processing for TLS connections that have been |
3976 | * upgraded. This requires a separate epoll() invocation as we | 4021 | * upgraded. This requires a separate epoll() invocation as we |
3977 | * cannot use the `struct MHD_Connection` data structures for | 4022 | * cannot use the `struct MHD_Connection` data structures for |
@@ -3984,6 +4029,8 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon) | |||
3984 | { | 4029 | { |
3985 | struct epoll_event events[MAX_EVENTS]; | 4030 | struct epoll_event events[MAX_EVENTS]; |
3986 | int num_events; | 4031 | int num_events; |
4032 | struct MHD_UpgradeResponseHandle * pos; | ||
4033 | struct MHD_UpgradeResponseHandle * prev; | ||
3987 | 4034 | ||
3988 | num_events = MAX_EVENTS; | 4035 | num_events = MAX_EVENTS; |
3989 | while (MAX_EVENTS == num_events) | 4036 | while (MAX_EVENTS == num_events) |
@@ -4006,45 +4053,74 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon) | |||
4006 | #endif | 4053 | #endif |
4007 | return MHD_NO; | 4054 | return MHD_NO; |
4008 | } | 4055 | } |
4009 | for (i=0;i<(unsigned int) num_events;i++) | 4056 | for (i = 0; i < (unsigned int) num_events; i++) |
4010 | { | 4057 | { |
4011 | struct UpgradeEpollHandle * const ueh = events[i].data.ptr; | 4058 | struct UpgradeEpollHandle * const ueh = events[i].data.ptr; |
4012 | struct MHD_UpgradeResponseHandle * const urh = ueh->urh; | 4059 | struct MHD_UpgradeResponseHandle * const urh = ueh->urh; |
4060 | bool new_err_state = false; | ||
4013 | 4061 | ||
4014 | /* Each MHD_UpgradeResponseHandle can be processed two times: | ||
4015 | * one time for TLS data and one time for socketpair data. | ||
4016 | * If forwarding was finished on first time, second time must | ||
4017 | * be skipped as urh must not be used anymore. */ | ||
4018 | if (urh->clean_ready) | 4062 | if (urh->clean_ready) |
4019 | continue; | 4063 | continue; |
4020 | 4064 | ||
4021 | /* Update our state based on what is ready according to epoll() */ | 4065 | /* Update ueh state based on what is ready according to epoll() */ |
4022 | if (0 != (events[i].events & EPOLLIN)) | 4066 | if (0 != (events[i].events & EPOLLIN)) |
4023 | ueh->celi |= MHD_EPOLL_STATE_READ_READY; | 4067 | ueh->celi |= MHD_EPOLL_STATE_READ_READY; |
4024 | if (0 != (events[i].events & EPOLLOUT)) | 4068 | if (0 != (events[i].events & EPOLLOUT)) |
4025 | ueh->celi |= MHD_EPOLL_STATE_WRITE_READY; | 4069 | ueh->celi |= MHD_EPOLL_STATE_WRITE_READY; |
4026 | if (0 != (events[i].events & EPOLLHUP)) | 4070 | if (0 != (events[i].events & EPOLLHUP)) |
4027 | ueh->celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY; | 4071 | ueh->celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY; |
4028 | if (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) | ||
4029 | ueh->celi |= MHD_EPOLL_STATE_ERROR; | ||
4030 | 4072 | ||
4031 | process_urh (urh); | 4073 | if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) && |
4032 | /* Finished forwarding? */ | 4074 | (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) ) |
4033 | if ( (0 == urh->in_buffer_size) && | 4075 | { |
4034 | (0 == urh->out_buffer_size) && | 4076 | /* Process new error state only one time |
4035 | (0 == urh->in_buffer_used) && | 4077 | * and avoid continuously marking this connection |
4036 | (0 == urh->out_buffer_used) ) | 4078 | * as 'ready'. */ |
4079 | ueh->celi |= MHD_EPOLL_STATE_ERROR; | ||
4080 | new_err_state = true; | ||
4081 | } | ||
4082 | |||
4083 | if (! urh->in_eready_list) | ||
4037 | { | 4084 | { |
4038 | MHD_connection_finish_forward_ (urh->connection); | 4085 | if (new_err_state || |
4039 | urh->clean_ready = true; | 4086 | is_urh_ready(urh)) |
4040 | /* If 'urh->was_closed' set to true, connection will be | 4087 | { |
4041 | * moved immediately to cleanup list. Otherwise connection | 4088 | EDLL_insert (daemon->eready_urh_head, |
4042 | * will stay in suspended list until 'urh' will be marked | 4089 | daemon->eready_urh_tail, |
4043 | * with 'was_closed' by application. */ | 4090 | urh); |
4044 | MHD_resume_connection(urh->connection); | 4091 | urh->in_eready_list = true; |
4092 | } | ||
4045 | } | 4093 | } |
4046 | } | 4094 | } |
4047 | } | 4095 | } |
4096 | prev = daemon->eready_urh_tail; | ||
4097 | while (NULL != (pos = prev)) | ||
4098 | { | ||
4099 | prev = pos->prevE; | ||
4100 | process_urh (pos); | ||
4101 | if (! is_urh_ready(pos)) | ||
4102 | { | ||
4103 | EDLL_remove (daemon->eready_urh_head, | ||
4104 | daemon->eready_urh_tail, | ||
4105 | pos); | ||
4106 | pos->in_eready_list = false; | ||
4107 | } | ||
4108 | /* Finished forwarding? */ | ||
4109 | if ( (0 == pos->in_buffer_size) && | ||
4110 | (0 == pos->out_buffer_size) && | ||
4111 | (0 == pos->in_buffer_used) && | ||
4112 | (0 == pos->out_buffer_used) ) | ||
4113 | { | ||
4114 | MHD_connection_finish_forward_ (pos->connection); | ||
4115 | pos->clean_ready = true; | ||
4116 | /* If 'pos->was_closed' already was set to true, connection | ||
4117 | * will be moved immediately to cleanup list. Otherwise | ||
4118 | * connection will stay in suspended list until 'pos' will | ||
4119 | * be marked with 'was_closed' by application. */ | ||
4120 | MHD_resume_connection(pos->connection); | ||
4121 | } | ||
4122 | } | ||
4123 | |||
4048 | return MHD_YES; | 4124 | return MHD_YES; |
4049 | } | 4125 | } |
4050 | #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ | 4126 | #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ |