aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2021-04-01 17:52:08 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2021-04-01 17:52:08 +0300
commitbf25ee3a3220596b83b6530b06d4106f2f0bfda1 (patch)
tree0174373da1f855a666b0cfe8408af3b187a9d54b /src/microhttpd/daemon.c
parentfcca12c2708013aef90efc15e34805a158ce58d6 (diff)
downloadlibmicrohttpd-bf25ee3a3220596b83b6530b06d4106f2f0bfda1.tar.gz
libmicrohttpd-bf25ee3a3220596b83b6530b06d4106f2f0bfda1.zip
Implemented new API function MHD_run_wait().
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c201
1 files changed, 140 insertions, 61 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0fe47228..59eaf953 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -101,16 +101,17 @@ close_all_connections (struct MHD_Daemon *daemon);
101#ifdef EPOLL_SUPPORT 101#ifdef EPOLL_SUPPORT
102 102
103/** 103/**
104 * Do epoll()-based processing (this function is allowed to 104 * Do epoll()-based processing.
105 * block if @a may_block is set to #MHD_YES).
106 * 105 *
107 * @param daemon daemon to run poll loop for 106 * @param daemon daemon to run poll loop for
108 * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking 107 * @param millisec the maximum time in milliseconds to wait for events,
108 * set to '0' for non-blocking processing,
109 * set to '-1' to wait indefinitely.
109 * @return #MHD_NO on serious errors, #MHD_YES on success 110 * @return #MHD_NO on serious errors, #MHD_YES on success
110 */ 111 */
111static enum MHD_Result 112static enum MHD_Result
112MHD_epoll (struct MHD_Daemon *daemon, 113MHD_epoll (struct MHD_Daemon *daemon,
113 int may_block); 114 int32_t millisec);
114 115
115#endif /* EPOLL_SUPPORT */ 116#endif /* EPOLL_SUPPORT */
116 117
@@ -3835,6 +3836,35 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
3835 3836
3836 3837
3837/** 3838/**
3839 * Obtain timeout value for polling function for this daemon.
3840 * @remark To be called only from the thread that processes
3841 * daemon's select()/poll()/etc.
3842 *
3843 * @param daemon the daemon to query for timeout
3844 * @param max_timeout the maximum return value (in milliseconds),
3845 * ignored if set to '-1'
3846 * @return timeout value in milliseconds or -1 if no timeout is expected.
3847 */
3848static int
3849get_timeout_millisec_ (struct MHD_Daemon *daemon,
3850 int32_t max_timeout)
3851{
3852 MHD_UNSIGNED_LONG_LONG ulltimeout;
3853 if (0 == max_timeout)
3854 return 0;
3855
3856 if (MHD_NO == MHD_get_timeout (daemon, &ulltimeout))
3857 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3858
3859 if ( (0 > max_timeout) ||
3860 ((uint32_t) max_timeout > ulltimeout) )
3861 return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
3862
3863 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3864}
3865
3866
3867/**
3838 * Internal version of #MHD_run_from_select(). 3868 * Internal version of #MHD_run_from_select().
3839 * 3869 *
3840 * @param daemon daemon to run select loop for 3870 * @param daemon daemon to run select loop for
@@ -3978,7 +4008,7 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
3978 { 4008 {
3979#ifdef EPOLL_SUPPORT 4009#ifdef EPOLL_SUPPORT
3980 enum MHD_Result ret = MHD_epoll (daemon, 4010 enum MHD_Result ret = MHD_epoll (daemon,
3981 MHD_NO); 4011 0);
3982 4012
3983 MHD_cleanup_connections (daemon); 4013 MHD_cleanup_connections (daemon);
3984 return ret; 4014 return ret;
@@ -4003,12 +4033,14 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
4003 * and then #internal_run_from_select with the result. 4033 * and then #internal_run_from_select with the result.
4004 * 4034 *
4005 * @param daemon daemon to run select() loop for 4035 * @param daemon daemon to run select() loop for
4006 * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking 4036 * @param millisec the maximum time in milliseconds to wait for events,
4037 * set to '0' for non-blocking processing,
4038 * set to '-1' to wait indefinitely.
4007 * @return #MHD_NO on serious errors, #MHD_YES on success 4039 * @return #MHD_NO on serious errors, #MHD_YES on success
4008 */ 4040 */
4009static enum MHD_Result 4041static enum MHD_Result
4010MHD_select (struct MHD_Daemon *daemon, 4042MHD_select (struct MHD_Daemon *daemon,
4011 int may_block) 4043 int32_t millisec)
4012{ 4044{
4013 int num_ready; 4045 int num_ready;
4014 fd_set rs; 4046 fd_set rs;
@@ -4017,7 +4049,6 @@ MHD_select (struct MHD_Daemon *daemon,
4017 MHD_socket maxsock; 4049 MHD_socket maxsock;
4018 struct timeval timeout; 4050 struct timeval timeout;
4019 struct timeval *tv; 4051 struct timeval *tv;
4020 MHD_UNSIGNED_LONG_LONG ltimeout;
4021 int err_state; 4052 int err_state;
4022 MHD_socket ls; 4053 MHD_socket ls;
4023 4054
@@ -4033,7 +4064,7 @@ MHD_select (struct MHD_Daemon *daemon,
4033 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) && 4064 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4034 (MHD_NO != resume_suspended_connections (daemon)) && 4065 (MHD_NO != resume_suspended_connections (daemon)) &&
4035 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ) 4066 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
4036 may_block = MHD_NO; 4067 millisec = 0;
4037 4068
4038 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 4069 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4039 { 4070 {
@@ -4118,25 +4149,47 @@ MHD_select (struct MHD_Daemon *daemon,
4118 FD_CLR (ls, 4149 FD_CLR (ls,
4119 &rs); 4150 &rs);
4120 } 4151 }
4121 tv = NULL; 4152
4122 if (MHD_NO != err_state) 4153 if (MHD_NO != err_state)
4123 may_block = MHD_NO; 4154 millisec = 0;
4124 if (MHD_NO == may_block) 4155 tv = NULL;
4156 if (0 == millisec)
4125 { 4157 {
4126 timeout.tv_usec = 0; 4158 timeout.tv_usec = 0;
4127 timeout.tv_sec = 0; 4159 timeout.tv_sec = 0;
4128 tv = &timeout; 4160 tv = &timeout;
4129 } 4161 }
4130 else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && 4162 else
4131 (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
4132 { 4163 {
4133 /* ltimeout is in ms */ 4164 MHD_UNSIGNED_LONG_LONG ltimeout;
4134 timeout.tv_usec = (ltimeout % 1000) * 1000; 4165
4135 if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX) 4166 if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
4136 timeout.tv_sec = TIMEVAL_TV_SEC_MAX; 4167 (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
4137 else 4168 {
4138 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000); 4169 tv = &timeout; /* have timeout value */
4139 tv = &timeout; 4170 if ( (0 < millisec) &&
4171 (ltimeout > (MHD_UNSIGNED_LONG_LONG) millisec) )
4172 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4173 }
4174 else if (0 < millisec)
4175 {
4176 tv = &timeout; /* have timeout value */
4177 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4178 }
4179
4180 if (NULL != tv)
4181 { /* have timeout value */
4182 if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
4183 {
4184 timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
4185 timeout.tv_usec = 0;
4186 }
4187 else
4188 {
4189 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
4190 timeout.tv_usec = (ltimeout % 1000) * 1000;
4191 }
4192 }
4140 } 4193 }
4141 num_ready = MHD_SYS_select_ (maxsock + 1, 4194 num_ready = MHD_SYS_select_ (maxsock + 1,
4142 &rs, 4195 &rs,
@@ -4172,12 +4225,14 @@ MHD_select (struct MHD_Daemon *daemon,
4172 * socket using poll(). 4225 * socket using poll().
4173 * 4226 *
4174 * @param daemon daemon to run poll loop for 4227 * @param daemon daemon to run poll loop for
4175 * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking 4228 * @param millisec the maximum time in milliseconds to wait for events,
4229 * set to '0' for non-blocking processing,
4230 * set to '-1' to wait indefinitely.
4176 * @return #MHD_NO on serious errors, #MHD_YES on success 4231 * @return #MHD_NO on serious errors, #MHD_YES on success
4177 */ 4232 */
4178static enum MHD_Result 4233static enum MHD_Result
4179MHD_poll_all (struct MHD_Daemon *daemon, 4234MHD_poll_all (struct MHD_Daemon *daemon,
4180 int may_block) 4235 int32_t millisec)
4181{ 4236{
4182 unsigned int num_connections; 4237 unsigned int num_connections;
4183 struct MHD_Connection *pos; 4238 struct MHD_Connection *pos;
@@ -4189,7 +4244,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
4189 4244
4190 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) && 4245 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4191 (MHD_NO != resume_suspended_connections (daemon)) ) 4246 (MHD_NO != resume_suspended_connections (daemon)) )
4192 may_block = MHD_NO; 4247 millisec = 0;
4193 4248
4194 /* count number of connections and thus determine poll set size */ 4249 /* count number of connections and thus determine poll set size */
4195 num_connections = 0; 4250 num_connections = 0;
@@ -4200,7 +4255,6 @@ MHD_poll_all (struct MHD_Daemon *daemon,
4200 num_connections += 2; 4255 num_connections += 2;
4201#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 4256#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4202 { 4257 {
4203 MHD_UNSIGNED_LONG_LONG ltimeout;
4204 unsigned int i; 4258 unsigned int i;
4205 int timeout; 4259 int timeout;
4206 unsigned int poll_server; 4260 unsigned int poll_server;
@@ -4243,14 +4297,8 @@ MHD_poll_all (struct MHD_Daemon *daemon,
4243 poll_itc_idx = (int) poll_server; 4297 poll_itc_idx = (int) poll_server;
4244 poll_server++; 4298 poll_server++;
4245 } 4299 }
4246 if (may_block == MHD_NO) 4300
4247 timeout = 0; 4301 timeout = get_timeout_millisec_ (daemon, millisec);
4248 else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
4249 (MHD_NO == MHD_get_timeout (daemon,
4250 &ltimeout)) )
4251 timeout = -1;
4252 else
4253 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
4254 4302
4255 i = 0; 4303 i = 0;
4256 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev) 4304 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
@@ -4494,7 +4542,7 @@ MHD_poll (struct MHD_Daemon *daemon,
4494 return MHD_NO; 4542 return MHD_NO;
4495 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 4543 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4496 return MHD_poll_all (daemon, 4544 return MHD_poll_all (daemon,
4497 may_block); 4545 may_block ? -1 : 0);
4498 return MHD_poll_listen_socket (daemon, 4546 return MHD_poll_listen_socket (daemon,
4499 may_block); 4547 may_block);
4500#else 4548#else
@@ -4685,16 +4733,17 @@ static const char *const epoll_itc_marker = "itc_marker";
4685 4733
4686 4734
4687/** 4735/**
4688 * Do epoll()-based processing (this function is allowed to 4736 * Do epoll()-based processing.
4689 * block if @a may_block is set to #MHD_YES).
4690 * 4737 *
4691 * @param daemon daemon to run poll loop for 4738 * @param daemon daemon to run poll loop for
4692 * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking 4739 * @param millisec the maximum time in milliseconds to wait for events,
4740 * set to '0' for non-blocking processing,
4741 * set to '-1' to wait indefinitely.
4693 * @return #MHD_NO on serious errors, #MHD_YES on success 4742 * @return #MHD_NO on serious errors, #MHD_YES on success
4694 */ 4743 */
4695static enum MHD_Result 4744static enum MHD_Result
4696MHD_epoll (struct MHD_Daemon *daemon, 4745MHD_epoll (struct MHD_Daemon *daemon,
4697 int may_block) 4746 int32_t millisec)
4698{ 4747{
4699#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4748#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4700 static const char *const upgrade_marker = "upgrade_ptr"; 4749 static const char *const upgrade_marker = "upgrade_ptr";
@@ -4704,7 +4753,6 @@ MHD_epoll (struct MHD_Daemon *daemon,
4704 struct epoll_event events[MAX_EVENTS]; 4753 struct epoll_event events[MAX_EVENTS];
4705 struct epoll_event event; 4754 struct epoll_event event;
4706 int timeout_ms; 4755 int timeout_ms;
4707 MHD_UNSIGNED_LONG_LONG timeout_ll;
4708 int num_events; 4756 int num_events;
4709 unsigned int i; 4757 unsigned int i;
4710 MHD_socket ls; 4758 MHD_socket ls;
@@ -4790,23 +4838,9 @@ MHD_epoll (struct MHD_Daemon *daemon,
4790 4838
4791 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) && 4839 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4792 (MHD_NO != resume_suspended_connections (daemon)) ) 4840 (MHD_NO != resume_suspended_connections (daemon)) )
4793 may_block = MHD_NO; 4841 millisec = 0;
4794 4842
4795 if (MHD_NO != may_block) 4843 timeout_ms = get_timeout_millisec_ (daemon, millisec);
4796 {
4797 if (MHD_NO != MHD_get_timeout (daemon,
4798 &timeout_ll))
4799 {
4800 if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4801 timeout_ms = INT_MAX;
4802 else
4803 timeout_ms = (int) timeout_ll;
4804 }
4805 else
4806 timeout_ms = -1;
4807 }
4808 else
4809 timeout_ms = 0;
4810 4844
4811 /* Reset. New value will be set when connections are processed. */ 4845 /* Reset. New value will be set when connections are processed. */
4812 /* Note: Used mostly for uniformity here as same situation is 4846 /* Note: Used mostly for uniformity here as same situation is
@@ -5026,24 +5060,69 @@ MHD_run (struct MHD_Daemon *daemon)
5026 if ( (daemon->shutdown) || 5060 if ( (daemon->shutdown) ||
5027 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ) 5061 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5028 return MHD_NO; 5062 return MHD_NO;
5063
5064 (void) MHD_run_wait (daemon, 0);
5065 return MHD_YES;
5066}
5067
5068
5069/**
5070 * Run websever operation with possible blocking.
5071 * This function do the following: waits for any network event not more than
5072 * specified number of milliseconds, processes all incoming and outgoing
5073 * data, processes new connections, processes any timed-out connection, and
5074 * do other things required to run webserver.
5075 * Once all connections are processed, function returns.
5076 * This function is useful for quick and simple webserver implementation if
5077 * application needs to run a single thread only and does not have any other
5078 * network activity.
5079 * @param daemon the daemon to run
5080 * @param millisec the maximum time in milliseconds to wait for network and
5081 * other events. Note: there is no guarantee that function
5082 * blocks for specified amount of time. The real processing
5083 * time can be shorter (if some data comes earlier) or
5084 * longer (if data processing requires more time, especially
5085 * in the user callbacks).
5086 * If set to '0' then function does not block and processes
5087 * only already available data (if any).
5088 * If set to '-1' then function waits for events
5089 * indefinitely (blocks until next network activity).
5090 * @return #MHD_YES on success, #MHD_NO if this
5091 * daemon was not started with the right
5092 * options for this call or some serious
5093 * unrecoverable error occurs.
5094 * @note Available since #MHD_VERSION 0x00097206
5095 * @ingroup event
5096 */
5097enum MHD_Result
5098MHD_run_wait (struct MHD_Daemon *daemon,
5099 int32_t millisec)
5100{
5101 enum MHD_Result res;
5102 if ( (daemon->shutdown) ||
5103 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5104 return MHD_NO;
5105
5106 if (0 > millisec)
5107 millisec = -1;
5029 if (0 != (daemon->options & MHD_USE_POLL)) 5108 if (0 != (daemon->options & MHD_USE_POLL))
5030 { 5109 {
5031 MHD_poll (daemon, MHD_NO); 5110 res = MHD_poll_all (daemon, millisec);
5032 MHD_cleanup_connections (daemon); 5111 MHD_cleanup_connections (daemon);
5033 } 5112 }
5034#ifdef EPOLL_SUPPORT 5113#ifdef EPOLL_SUPPORT
5035 else if (0 != (daemon->options & MHD_USE_EPOLL)) 5114 else if (0 != (daemon->options & MHD_USE_EPOLL))
5036 { 5115 {
5037 MHD_epoll (daemon, MHD_NO); 5116 res = MHD_epoll (daemon, millisec);
5038 MHD_cleanup_connections (daemon); 5117 MHD_cleanup_connections (daemon);
5039 } 5118 }
5040#endif 5119#endif
5041 else 5120 else
5042 { 5121 {
5043 MHD_select (daemon, MHD_NO); 5122 res = MHD_select (daemon, millisec);
5044 /* MHD_select does MHD_cleanup_connections already */ 5123 /* MHD_select does MHD_cleanup_connections already */
5045 } 5124 }
5046 return MHD_YES; 5125 return res;
5047} 5126}
5048 5127
5049 5128
@@ -5139,10 +5218,10 @@ MHD_polling_thread (void *cls)
5139 MHD_poll (daemon, MHD_YES); 5218 MHD_poll (daemon, MHD_YES);
5140#ifdef EPOLL_SUPPORT 5219#ifdef EPOLL_SUPPORT
5141 else if (0 != (daemon->options & MHD_USE_EPOLL)) 5220 else if (0 != (daemon->options & MHD_USE_EPOLL))
5142 MHD_epoll (daemon, MHD_YES); 5221 MHD_epoll (daemon, -1);
5143#endif 5222#endif
5144 else 5223 else
5145 MHD_select (daemon, MHD_YES); 5224 MHD_select (daemon, -1);
5146 MHD_cleanup_connections (daemon); 5225 MHD_cleanup_connections (daemon);
5147 } 5226 }
5148 5227