diff options
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r-- | src/microhttpd/connection.c | 163 |
1 files changed, 96 insertions, 67 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index bd8af585..43a90ee0 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -154,25 +154,40 @@ socket_start_extra_buffering (struct MHD_Connection *connection) | |||
154 | return MHD_NO; | 154 | return MHD_NO; |
155 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) | 155 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) |
156 | /* Buffer data before sending */ | 156 | /* Buffer data before sending */ |
157 | res = (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&on_val, | 157 | res = (0 == setsockopt (connection->socket_fd, |
158 | sizeof (on_val))) ? MHD_YES : MHD_NO; | 158 | IPPROTO_TCP, |
159 | TCP_NOPUSH, | ||
160 | (const void *) &on_val, | ||
161 | sizeof (on_val))) | ||
162 | ? MHD_YES : MHD_NO; | ||
159 | #if defined(TCP_NODELAY) | 163 | #if defined(TCP_NODELAY) |
160 | /* Enable Nagle's algorithm */ | 164 | /* Enable Nagle's algorithm */ |
161 | /* TCP_NODELAY may interfere with TCP_NOPUSH */ | 165 | /* TCP_NODELAY may interfere with TCP_NOPUSH */ |
162 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, | 166 | res &= (0 == setsockopt (connection->socket_fd, |
163 | sizeof (off_val))) ? MHD_YES : MHD_NO; | 167 | IPPROTO_TCP, |
168 | TCP_NODELAY, | ||
169 | (const void *) &off_val, | ||
170 | sizeof (off_val))) | ||
171 | ? MHD_YES : MHD_NO; | ||
164 | #endif /* TCP_NODELAY */ | 172 | #endif /* TCP_NODELAY */ |
165 | #else /* TCP_CORK */ | 173 | #else /* TCP_CORK */ |
166 | #if defined(TCP_NODELAY) | 174 | #if defined(TCP_NODELAY) |
167 | /* Enable Nagle's algorithm */ | 175 | /* Enable Nagle's algorithm */ |
168 | /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends | 176 | /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends |
169 | solely on TCP_CORK result, so ignoring return code here. */ | 177 | solely on TCP_CORK result, so ignoring return code here. */ |
170 | (void)setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, | 178 | (void) setsockopt (connection->socket_fd, |
171 | sizeof (off_val)); | 179 | IPPROTO_TCP, |
180 | TCP_NODELAY, | ||
181 | (const void *) &off_val, | ||
182 | sizeof (off_val)); | ||
172 | #endif /* TCP_NODELAY */ | 183 | #endif /* TCP_NODELAY */ |
173 | /* Send only full packets */ | 184 | /* Send only full packets */ |
174 | res = (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&on_val, | 185 | res = (0 == setsockopt (connection->socket_fd, |
175 | sizeof (on_val))) ? MHD_YES : MHD_NO; | 186 | IPPROTO_TCP, |
187 | TCP_CORK, | ||
188 | (const void *) &on_val, | ||
189 | sizeof (on_val))) | ||
190 | ? MHD_YES : MHD_NO; | ||
176 | #endif /* TCP_CORK */ | 191 | #endif /* TCP_CORK */ |
177 | #endif /* TCP_CORK || TCP_NOPUSH */ | 192 | #endif /* TCP_CORK || TCP_NOPUSH */ |
178 | return res; | 193 | return res; |
@@ -180,88 +195,86 @@ socket_start_extra_buffering (struct MHD_Connection *connection) | |||
180 | 195 | ||
181 | 196 | ||
182 | /** | 197 | /** |
183 | * Activate no buffering mode (no delay sending) on connection socket | 198 | * Activate no buffering mode (no delay sending) on connection socket. |
184 | * and push to client data pending in socket buffer. | ||
185 | * | 199 | * |
186 | * @param connection connection to be processed | 200 | * @param connection connection to be processed |
187 | * @return #MHD_YES on success, #MHD_NO otherwise | 201 | * @return #MHD_YES on success, #MHD_NO otherwise |
188 | */ | 202 | */ |
189 | static int | 203 | static int |
190 | socket_start_no_buffering_flush (struct MHD_Connection *connection) | 204 | socket_start_no_buffering (struct MHD_Connection *connection) |
191 | { | 205 | { |
192 | #if defined(TCP_CORK) || defined(TCP_NOPUSH) | ||
193 | int res = MHD_YES; | ||
194 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
195 | #if defined(TCP_NODELAY) | 206 | #if defined(TCP_NODELAY) |
207 | int res = MHD_YES; | ||
196 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | 208 | const MHD_SCKT_OPT_BOOL_ on_val = 1; |
197 | #endif /* TCP_NODELAY */ | 209 | #if defined(TCP_CORK) || defined(TCP_NOPUSH) |
198 | #if !defined(TCP_CORK) | 210 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
199 | const int dummy = 0; | 211 | #endif /* TCP_CORK || TCP_NOPUSH */ |
200 | #endif /* !TCP_CORK */ | 212 | |
201 | if (!connection) | 213 | if (NULL == connection) |
202 | return MHD_NO; | 214 | return MHD_NO; |
203 | #if defined(TCP_CORK) | 215 | #if defined(TCP_CORK) |
204 | /* Flush buffered data, allow partial packets */ | 216 | /* Allow partial packets */ |
205 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&off_val, | 217 | res &= (0 == setsockopt (connection->socket_fd, |
206 | sizeof (off_val))) ? MHD_YES : MHD_NO; | 218 | IPPROTO_TCP, |
219 | TCP_CORK, | ||
220 | (const void *) &off_val, | ||
221 | sizeof (off_val))) | ||
222 | ? MHD_YES : MHD_NO; | ||
207 | #endif /* TCP_CORK */ | 223 | #endif /* TCP_CORK */ |
208 | #if defined(TCP_NODELAY) | 224 | #if defined(TCP_NODELAY) |
209 | /* Disable Nagle's algorithm */ | 225 | /* Disable Nagle's algorithm for sending packets without delay */ |
210 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&on_val, | 226 | res &= (0 == setsockopt (connection->socket_fd, |
211 | sizeof (on_val))) ? MHD_YES : MHD_NO; | 227 | IPPROTO_TCP, |
228 | TCP_NODELAY, | ||
229 | (const void *) &on_val, | ||
230 | sizeof (on_val))) | ||
231 | ? MHD_YES : MHD_NO; | ||
212 | #endif /* TCP_NODELAY */ | 232 | #endif /* TCP_NODELAY */ |
213 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) | 233 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) |
214 | /* Send data without extra buffering, may flush pending data on some platforms */ | 234 | /* Disable extra buffering */ |
215 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&off_val, | 235 | res &= (0 == setsockopt (connection->socket_fd, |
216 | sizeof (off_val))) ? MHD_YES : MHD_NO; | 236 | IPPROTO_TCP, |
217 | /* Force flush data with zero send otherwise Darwin and some BSD systems | 237 | TCP_NOPUSH, |
218 | will add 5 seconds delay. Not required with TCP_CORK as switching off | 238 | (const void *) &off_val, |
219 | TCP_CORK always flushes socket buffer. */ | 239 | sizeof (off_val))) |
220 | res &= (0 <= send (connection->socket_fd, (const void*)&dummy, 0, 0)) ? MHD_YES : MHD_NO; | 240 | ? MHD_YES : MHD_NO; |
221 | #endif /* TCP_NOPUSH && !TCP_CORK*/ | 241 | #endif /* TCP_NOPUSH && !TCP_CORK */ |
222 | return res; | 242 | return res; |
223 | #else /* !TCP_CORK && !TCP_NOPUSH */ | 243 | #else /* !TCP_NODELAY */ |
224 | return MHD_NO; | 244 | return MHD_NO; |
225 | #endif /* !TCP_CORK && !TCP_NOPUSH */ | 245 | #endif /* !TCP_NODELAY */ |
226 | } | 246 | } |
227 | 247 | ||
228 | 248 | ||
229 | /** | 249 | /** |
230 | * Activate no buffering mode (no delay sending) on connection socket. | 250 | * Activate no buffering mode (no delay sending) on connection socket |
251 | * and push to client data pending in socket buffer. | ||
231 | * | 252 | * |
232 | * @param connection connection to be processed | 253 | * @param connection connection to be processed |
233 | * @return #MHD_YES on success, #MHD_NO otherwise | 254 | * @return #MHD_YES on success, #MHD_NO otherwise |
234 | */ | 255 | */ |
235 | static int | 256 | static int |
236 | socket_start_no_buffering (struct MHD_Connection *connection) | 257 | socket_start_no_buffering_flush (struct MHD_Connection *connection) |
237 | { | 258 | { |
238 | #if defined(TCP_NODELAY) | ||
239 | int res = MHD_YES; | 259 | int res = MHD_YES; |
240 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | 260 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) |
241 | #if defined(TCP_CORK) || defined(TCP_NOPUSH) | 261 | const int dummy = 0; |
242 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | 262 | #endif /* !TCP_CORK */ |
243 | #endif /* TCP_CORK || TCP_NOPUSH */ | 263 | |
244 | if (!connection) | 264 | if (NULL == connection) |
245 | return MHD_NO; | 265 | return MHD_NO; |
246 | #if defined(TCP_CORK) | 266 | res = socket_start_no_buffering (connection); |
247 | /* Allow partial packets */ | ||
248 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&off_val, | ||
249 | sizeof (off_val))) ? MHD_YES : MHD_NO; | ||
250 | #endif /* TCP_CORK */ | ||
251 | #if defined(TCP_NODELAY) | ||
252 | /* Disable Nagle's algorithm for sending packets without delay */ | ||
253 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&on_val, | ||
254 | sizeof (on_val))) ? MHD_YES : MHD_NO; | ||
255 | #endif /* TCP_NODELAY */ | ||
256 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) | 267 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) |
257 | /* Disable extra buffering */ | 268 | /* Force flush data with zero send otherwise Darwin and some BSD systems |
258 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&off_val, | 269 | will add 5 seconds delay. Not required with TCP_CORK as switching off |
259 | sizeof (off_val))) ? MHD_YES : MHD_NO; | 270 | TCP_CORK always flushes socket buffer. */ |
260 | #endif /* TCP_NOPUSH && !TCP_CORK */ | 271 | res &= (0 <= send (connection->socket_fd, |
272 | (const void *) &dummy, | ||
273 | 0, | ||
274 | 0)) | ||
275 | ? MHD_YES : MHD_NO; | ||
276 | #endif /* TCP_NOPUSH && !TCP_CORK*/ | ||
261 | return res; | 277 | return res; |
262 | #else /* !TCP_NODELAY */ | ||
263 | return MHD_NO; | ||
264 | #endif /* !TCP_NODELAY */ | ||
265 | } | 278 | } |
266 | 279 | ||
267 | 280 | ||
@@ -287,20 +300,36 @@ socket_start_normal_buffering (struct MHD_Connection *connection) | |||
287 | /* Allow partial packets */ | 300 | /* Allow partial packets */ |
288 | /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before | 301 | /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before |
289 | so try to check current value of TCP_CORK to prevent unrequested flushing */ | 302 | so try to check current value of TCP_CORK to prevent unrequested flushing */ |
290 | if ( (0 != getsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (void*)&cork_val, ¶m_size)) || | 303 | if ( (0 != getsockopt (connection->socket_fd, |
304 | IPPROTO_TCP, | ||
305 | TCP_CORK, | ||
306 | (void*)&cork_val, | ||
307 | ¶m_size)) || | ||
291 | (0 != cork_val)) | 308 | (0 != cork_val)) |
292 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&off_val, | 309 | res &= (0 == setsockopt (connection->socket_fd, |
293 | sizeof (off_val))) ? MHD_YES : MHD_NO; | 310 | IPPROTO_TCP, |
311 | TCP_CORK, | ||
312 | (const void *) &off_val, | ||
313 | sizeof (off_val))) | ||
314 | ? MHD_YES : MHD_NO; | ||
294 | #elif defined(TCP_NOPUSH) | 315 | #elif defined(TCP_NOPUSH) |
295 | /* Disable extra buffering */ | 316 | /* Disable extra buffering */ |
296 | /* No need to check current value as disabling TCP_NOPUSH will not flush partial | 317 | /* No need to check current value as disabling TCP_NOPUSH will not flush partial |
297 | packet if TCP_NOPUSH wasn't enabled before */ | 318 | packet if TCP_NOPUSH wasn't enabled before */ |
298 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&off_val, | 319 | res &= (0 == setsockopt (connection->socket_fd, |
299 | sizeof (off_val))) ? MHD_YES : MHD_NO; | 320 | IPPROTO_TCP, |
321 | TCP_NOPUSH, | ||
322 | (const void *) &off_val, | ||
323 | sizeof (off_val))) | ||
324 | ? MHD_YES : MHD_NO; | ||
300 | #endif /* TCP_NOPUSH && !TCP_CORK */ | 325 | #endif /* TCP_NOPUSH && !TCP_CORK */ |
301 | /* Enable Nagle's algorithm for normal buffering */ | 326 | /* Enable Nagle's algorithm for normal buffering */ |
302 | res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, | 327 | res &= (0 == setsockopt (connection->socket_fd, |
303 | sizeof (off_val))) ? MHD_YES : MHD_NO; | 328 | IPPROTO_TCP, |
329 | TCP_NODELAY, | ||
330 | (const void *) &off_val, | ||
331 | sizeof (off_val))) | ||
332 | ? MHD_YES : MHD_NO; | ||
304 | return res; | 333 | return res; |
305 | #else /* !TCP_NODELAY */ | 334 | #else /* !TCP_NODELAY */ |
306 | return MHD_NO; | 335 | return MHD_NO; |