aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/microhttpd/connection.c7
-rw-r--r--src/microhttpd/daemon.c120
-rw-r--r--src/microhttpd/internal.h31
-rw-r--r--src/microhttpd/response.c8
4 files changed, 141 insertions, 25 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 5c1a8611..36c05716 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -593,6 +593,13 @@ MHD_connection_finish_forward_ (struct MHD_Connection *connection)
593 { 593 {
594 MHD_PANIC (_("Failed to remove FD from epoll set\n")); 594 MHD_PANIC (_("Failed to remove FD from epoll set\n"));
595 } 595 }
596 if (urh->in_eready_list)
597 {
598 EDLL_remove (daemon->eready_urh_head,
599 daemon->eready_urh_tail,
600 urh);
601 urh->in_eready_list = false;
602 }
596#endif /* EPOLL_SUPPORT */ 603#endif /* EPOLL_SUPPORT */
597 if (MHD_INVALID_SOCKET != urh->mhd.socket) 604 if (MHD_INVALID_SOCKET != urh->mhd.socket)
598 { 605 {
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 */
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 44590878..5350c013 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -1026,6 +1026,23 @@ struct MHD_UpgradeResponseHandle
1026 */ 1026 */
1027 struct MHD_UpgradeResponseHandle *prev; 1027 struct MHD_UpgradeResponseHandle *prev;
1028 1028
1029#ifdef EPOLL_SUPPORT
1030 /**
1031 * Next pointer for the EDLL listing urhs that are epoll-ready.
1032 */
1033 struct MHD_UpgradeResponseHandle *nextE;
1034
1035 /**
1036 * Previous pointer for the EDLL listing urhs that are epoll-ready.
1037 */
1038 struct MHD_UpgradeResponseHandle *prevE;
1039
1040 /**
1041 * Specifies whether urh already in EDLL list of ready connections.
1042 */
1043 bool in_eready_list;
1044#endif
1045
1029 /** 1046 /**
1030 * The buffer for receiving data from TLS to 1047 * The buffer for receiving data from TLS to
1031 * be passed to the application. Contains @e in_buffer_size 1048 * be passed to the application. Contains @e in_buffer_size
@@ -1217,7 +1234,19 @@ struct MHD_Daemon
1217 * Tail of EDLL of connections ready for processing (in epoll mode) 1234 * Tail of EDLL of connections ready for processing (in epoll mode)
1218 */ 1235 */
1219 struct MHD_Connection *eready_tail; 1236 struct MHD_Connection *eready_tail;
1220#endif 1237
1238#ifdef UPGRADE_SUPPORT
1239 /**
1240 * Head of EDLL of upgraded connections ready for processing (in epoll mode).
1241 */
1242 struct MHD_UpgradeResponseHandle *eready_urh_head;
1243
1244 /**
1245 * Tail of EDLL of upgraded connections ready for processing (in epoll mode)
1246 */
1247 struct MHD_UpgradeResponseHandle *eready_urh_tail;
1248#endif /* UPGRADE_SUPPORT */
1249#endif /* EPOLL_SUPPORT */
1221 1250
1222 /** 1251 /**
1223 * Head of the XDLL of ALL connections with a default ('normal') 1252 * Head of the XDLL of ALL connections with a default ('normal')
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 9004013f..e8707480 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -851,7 +851,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
851 851
852 EXTRA_CHECK (-1 != daemon->epoll_upgrade_fd); 852 EXTRA_CHECK (-1 != daemon->epoll_upgrade_fd);
853 /* First, add network socket */ 853 /* First, add network socket */
854 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI; 854 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
855 event.data.ptr = &urh->app; 855 event.data.ptr = &urh->app;
856 if (0 != epoll_ctl (daemon->epoll_upgrade_fd, 856 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
857 EPOLL_CTL_ADD, 857 EPOLL_CTL_ADD,
@@ -870,7 +870,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
870 } 870 }
871 871
872 /* Second, add our end of the UNIX socketpair() */ 872 /* Second, add our end of the UNIX socketpair() */
873 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI; 873 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
874 event.data.ptr = &urh->mhd; 874 event.data.ptr = &urh->mhd;
875 if (0 != epoll_ctl (daemon->epoll_upgrade_fd, 875 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
876 EPOLL_CTL_ADD, 876 EPOLL_CTL_ADD,
@@ -894,6 +894,10 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
894 free (urh); 894 free (urh);
895 return MHD_NO; 895 return MHD_NO;
896 } 896 }
897 EDLL_insert (daemon->eready_urh_head,
898 daemon->eready_urh_tail,
899 urh);
900 urh->in_eready_list = true;
897 } 901 }
898#endif /* EPOLL_SUPPORT */ 902#endif /* EPOLL_SUPPORT */
899 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) ) 903 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )