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.c120
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 */
3985static bool
3986is_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 */