aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-10-17 16:52:29 +0200
committerChristian Grothoff <christian@grothoff.org>2019-10-17 16:52:29 +0200
commitcbbfd0591fc639ddd21a5850f54f403fb7394174 (patch)
tree97ac18a6fceceb8ad04d8125e3f5c2a6cd99e090
parent63a36813612a466c306297a5481c1e1e4f2e6164 (diff)
downloadlibmicrohttpd-cbbfd0591fc639ddd21a5850f54f403fb7394174.tar.gz
libmicrohttpd-cbbfd0591fc639ddd21a5850f54f403fb7394174.zip
presumably last touches on ng0's GSoC setsockopt refactoring
-rw-r--r--ChangeLog4
-rw-r--r--src/microhttpd/connection.c63
-rw-r--r--src/microhttpd/mhd_sockets.c282
3 files changed, 156 insertions, 193 deletions
diff --git a/ChangeLog b/ChangeLog
index b25b9365..1e890e9d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
1Thu 17 Oct 2019 04:50:52 PM CEST
2 Integrate 0-byte send() method for uncorking for old FreeBSD/OS X
3 systems into new mhd_send.c logic for uncorking. -CG
4
1Fri 18 Aug 2019 00:00:00 PM UTC 5Fri 18 Aug 2019 00:00:00 PM UTC
2 Fixes and optimizations for the setsockopt handling: 6 Fixes and optimizations for the setsockopt handling:
3 * Added: MHD_UPGRADE_ACTION_CORK_ON and MHD_UPGRADE_ACTION_CORK_OFF 7 * Added: MHD_UPGRADE_ACTION_CORK_ON and MHD_UPGRADE_ACTION_CORK_OFF
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 901cac0e..11c7099a 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -284,66 +284,6 @@ send_param_adapter (struct MHD_Connection *connection,
284 284
285 285
286/** 286/**
287 * Check whether is possible to force push socket buffer content as
288 * partial packet.
289 * MHD use different buffering logic depending on whether flushing of
290 * socket buffer is possible or not.
291 * If flushing IS possible than MHD activates extra buffering before
292 * sending data to prevent sending partial packets and flush pending
293 * data in socket buffer to push last partial packet to client after
294 * sending logical completed part of data (for example: after sending
295 * full response header or full response message).
296 * If flushing IS NOT possible than MHD activates no buffering (no
297 * delay sending) when it going to send formed fully completed logical
298 * part of data and activate normal buffering after sending.
299 * For idled keep-alive connection MHD always activate normal
300 * buffering.
301 *
302 * @param connection connection to check
303 * @return true if force push is possible, false otherwise
304 */
305_MHD_static_inline bool
306socket_flush_possible (struct MHD_Connection *connection)
307{
308 (void) connection; /* Mute compiler warning. */
309#if defined(TCP_CORK) || defined(TCP_PUSH)
310 return true;
311#else /* !TCP_CORK && !TCP_PUSH */
312 return false;
313#endif /* !TCP_CORK && !TCP_PUSH */
314}
315
316
317/**
318 * Activate no buffering mode (no delay sending) on connection socket
319 * and push to client data pending in socket buffer.
320 *
321 * @param connection connection to be processed
322 * @return true on success, false otherwise
323 */
324_MHD_static_inline bool
325socket_start_no_buffering_flush (struct MHD_Connection *connection)
326{
327 bool res = false;
328#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
329 const int dummy = 0;
330#endif /* !TCP_CORK */
331
332#if defined(__FreeBSD__) && __FreeBSD__ + 0 >= 9
333 /* FreeBSD do not need zero-send for flushing starting from version 9 */
334#elif defined(TCP_NOPUSH) && ! defined(TCP_CORK)
335 /* Force flush data with zero send otherwise Darwin and some BSD systems
336 will add 5 seconds delay. Not required with TCP_CORK as switching off
337 TCP_CORK always flushes socket buffer. */
338 res = (0 <= MHD_send_ (connection->socket_fd,
339 &dummy,
340 0)) && res;
341#endif /* TCP_NOPUSH && !TCP_CORK*/
342 return res;
343}
344
345
346/**
347 * Get all of the headers from the request. 287 * Get all of the headers from the request.
348 * 288 *
349 * @param connection connection to get values from 289 * @param connection connection to get values from
@@ -3593,9 +3533,6 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
3593 break; 3533 break;
3594 case MHD_CONNECTION_HEADERS_SENT: 3534 case MHD_CONNECTION_HEADERS_SENT:
3595 /* Some clients may take some actions right after header receive */ 3535 /* Some clients may take some actions right after header receive */
3596 if (socket_flush_possible (connection))
3597 socket_start_no_buffering_flush (connection); /* REMOVE: Dead */
3598
3599#ifdef UPGRADE_SUPPORT 3536#ifdef UPGRADE_SUPPORT
3600 if (NULL != connection->response->upgrade_handler) 3537 if (NULL != connection->response->upgrade_handler)
3601 { 3538 {
diff --git a/src/microhttpd/mhd_sockets.c b/src/microhttpd/mhd_sockets.c
index b4e73480..38c6ecd4 100644
--- a/src/microhttpd/mhd_sockets.c
+++ b/src/microhttpd/mhd_sockets.c
@@ -37,10 +37,10 @@
37 * @param err the WinSock error code. 37 * @param err the WinSock error code.
38 * @return pointer to string description of specified WinSock error. 38 * @return pointer to string description of specified WinSock error.
39 */ 39 */
40const char* MHD_W32_strerror_winsock_(int err) 40const char*MHD_W32_strerror_winsock_ (int err)
41{ 41{
42 switch (err) 42 switch (err)
43 { 43 {
44 case 0: 44 case 0:
45 return "No error"; 45 return "No error";
46 case WSA_INVALID_HANDLE: 46 case WSA_INVALID_HANDLE:
@@ -233,7 +233,7 @@ const char* MHD_W32_strerror_winsock_(int err)
233 return "Invalid QoS shaping rate object"; 233 return "Invalid QoS shaping rate object";
234 case WSA_QOS_RESERVED_PETYPE: 234 case WSA_QOS_RESERVED_PETYPE:
235 return "Reserved policy QoS element type"; 235 return "Reserved policy QoS element type";
236 } 236 }
237 return "Unknown winsock error"; 237 return "Unknown winsock error";
238} 238}
239 239
@@ -246,113 +246,114 @@ const char* MHD_W32_strerror_winsock_(int err)
246 * @return non-zero if succeeded, zero otherwise 246 * @return non-zero if succeeded, zero otherwise
247 */ 247 */
248int 248int
249MHD_W32_socket_pair_(SOCKET sockets_pair[2], int non_blk) 249MHD_W32_socket_pair_ (SOCKET sockets_pair[2], int non_blk)
250{ 250{
251 int i; 251 int i;
252 252
253 if (! sockets_pair) 253 if (! sockets_pair)
254 { 254 {
255 WSASetLastError (WSAEFAULT); 255 WSASetLastError (WSAEFAULT);
256 return 0; 256 return 0;
257 } 257 }
258 258
259#define PAIRMAXTRYIES 800 259#define PAIRMAXTRYIES 800
260 for (i = 0; i < PAIRMAXTRYIES; i++) 260 for (i = 0; i < PAIRMAXTRYIES; i++)
261 {
262 struct sockaddr_in listen_addr;
263 SOCKET listen_s;
264 static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */
265 int addr_len = c_addinlen;
266 unsigned long on_val = 1;
267 unsigned long off_val = 0;
268
269 listen_s = socket (AF_INET,
270 SOCK_STREAM,
271 IPPROTO_TCP);
272 if (INVALID_SOCKET == listen_s)
273 break; /* can't create even single socket */
274
275 listen_addr.sin_family = AF_INET;
276 listen_addr.sin_port = 0; /* same as htons(0) */
277 listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
278 if ( ((0 == bind (listen_s,
279 (struct sockaddr*) &listen_addr,
280 c_addinlen)) &&
281 (0 == listen (listen_s,
282 1) ) &&
283 (0 == getsockname (listen_s,
284 (struct sockaddr*) &listen_addr,
285 &addr_len))) )
261 { 286 {
262 struct sockaddr_in listen_addr; 287 SOCKET client_s = socket (AF_INET,
263 SOCKET listen_s; 288 SOCK_STREAM,
264 static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */ 289 IPPROTO_TCP);
265 int addr_len = c_addinlen; 290 struct sockaddr_in accepted_from_addr;
266 unsigned long on_val = 1; 291 struct sockaddr_in client_addr;
267 unsigned long off_val = 0; 292 SOCKET server_s;
268 293
269 listen_s = socket (AF_INET, 294 if (INVALID_SOCKET == client_s)
270 SOCK_STREAM, 295 {
271 IPPROTO_TCP); 296 /* try again */
272 if (INVALID_SOCKET == listen_s) 297 closesocket (listen_s);
273 break; /* can't create even single socket */ 298 continue;
274 299 }
275 listen_addr.sin_family = AF_INET; 300
276 listen_addr.sin_port = 0; /* same as htons(0) */ 301 if ( (0 != ioctlsocket (client_s,
277 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 302 FIONBIO,
278 if ( (0 == bind (listen_s, 303 &on_val)) ||
279 (struct sockaddr*) &listen_addr, 304 ( (0 != connect (client_s,
280 c_addinlen) && 305 (struct sockaddr*) &listen_addr,
281 (0 == listen (listen_s, 306 c_addinlen)) &&
282 1) ) && 307 (WSAGetLastError () != WSAEWOULDBLOCK)) )
283 (0 == getsockname (listen_s, 308 {
284 (struct sockaddr*) &listen_addr, 309 /* try again */
285 &addr_len))) ) 310 closesocket (listen_s);
286 { 311 closesocket (client_s);
287 SOCKET client_s = socket(AF_INET, 312 continue;
288 SOCK_STREAM, 313 }
289 IPPROTO_TCP); 314
290 struct sockaddr_in accepted_from_addr; 315 addr_len = c_addinlen;
291 struct sockaddr_in client_addr; 316 server_s = accept (listen_s,
292 SOCKET server_s; 317 (struct sockaddr*) &accepted_from_addr,
293 318 &addr_len);
294 if (INVALID_SOCKET == client_s) 319 if (INVALID_SOCKET == server_s)
295 { 320 {
296 /* try again */ 321 /* try again */
297 closesocket (listen_s); 322 closesocket (listen_s);
298 continue; 323 closesocket (client_s);
299 } 324 continue;
300 325 }
301 if ( (0 != ioctlsocket (client_s, 326
302 FIONBIO, 327 addr_len = c_addinlen;
303 &on_val)) || 328 if ( (0 == getsockname (client_s,
304 ( (0 != connect (client_s, 329 (struct sockaddr*) &client_addr,
305 (struct sockaddr*) &listen_addr, 330 &addr_len)) &&
306 c_addinlen)) && 331 (accepted_from_addr.sin_family == client_addr.sin_family) &&
307 (WSAGetLastError() != WSAEWOULDBLOCK)) ) 332 (accepted_from_addr.sin_port == client_addr.sin_port) &&
308 { 333 (accepted_from_addr.sin_addr.s_addr ==
309 /* try again */ 334 client_addr.sin_addr.s_addr) &&
310 closesocket (listen_s); 335 ( (0 != non_blk) ?
311 closesocket (client_s); 336 (0 == ioctlsocket (server_s,
312 continue; 337 FIONBIO,
313 } 338 &on_val)) :
314 339 (0 == ioctlsocket (client_s,
315 addr_len = c_addinlen; 340 FIONBIO,
316 server_s = accept (listen_s, 341 &off_val)) ) )
317 (struct sockaddr*) &accepted_from_addr, 342 {
318 &addr_len); 343 closesocket (listen_s);
319 if (INVALID_SOCKET == server_s) 344 sockets_pair[0] = server_s;
320 { 345 sockets_pair[1] = client_s;
321 /* try again */ 346 return ! 0;
322 closesocket (listen_s); 347 }
323 closesocket (client_s); 348 closesocket (server_s);
324 continue; 349 closesocket (client_s);
325 }
326
327 addr_len = c_addinlen;
328 if ( (0 == getsockname (client_s,
329 (struct sockaddr*) &client_addr,
330 &addr_len)) &&
331 (accepted_from_addr.sin_family == client_addr.sin_family) &&
332 (accepted_from_addr.sin_port == client_addr.sin_port) &&
333 (accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr) &&
334 ( (0 != non_blk) ?
335 (0 == ioctlsocket(server_s,
336 FIONBIO,
337 &on_val)) :
338 (0 == ioctlsocket(client_s,
339 FIONBIO,
340 &off_val)) ) )
341 {
342 closesocket (listen_s);
343 sockets_pair[0] = server_s;
344 sockets_pair[1] = client_s;
345 return !0;
346 }
347 closesocket (server_s);
348 closesocket (client_s);
349 }
350 closesocket(listen_s);
351 } 350 }
351 closesocket (listen_s);
352 }
352 353
353 sockets_pair[0] = INVALID_SOCKET; 354 sockets_pair[0] = INVALID_SOCKET;
354 sockets_pair[1] = INVALID_SOCKET; 355 sockets_pair[1] = INVALID_SOCKET;
355 WSASetLastError(WSAECONNREFUSED); 356 WSASetLastError (WSAECONNREFUSED);
356 357
357 return 0; 358 return 0;
358} 359}
@@ -383,9 +384,9 @@ MHD_add_to_fd_set_ (MHD_socket fd,
383 set, 384 set,
384 fd_setsize)) 385 fd_setsize))
385 return 0; 386 return 0;
386 MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_(fd, 387 MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_ (fd,
387 set, 388 set,
388 fd_setsize); 389 fd_setsize);
389 if ( (NULL != max_fd) && 390 if ( (NULL != max_fd) &&
390 ( (fd > *max_fd) || 391 ( (fd > *max_fd) ||
391 (MHD_INVALID_SOCKET == *max_fd) ) ) 392 (MHD_INVALID_SOCKET == *max_fd) ) )
@@ -424,7 +425,7 @@ MHD_socket_nonblocking_ (MHD_socket sock)
424 &flags)) 425 &flags))
425 return 0; 426 return 0;
426#endif /* MHD_WINSOCK_SOCKETS */ 427#endif /* MHD_WINSOCK_SOCKETS */
427 return !0; 428 return ! 0;
428} 429}
429 430
430 431
@@ -452,12 +453,12 @@ MHD_socket_noninheritable_ (MHD_socket sock)
452 flags | FD_CLOEXEC)) ) 453 flags | FD_CLOEXEC)) )
453 return 0; 454 return 0;
454#elif defined(MHD_WINSOCK_SOCKETS) 455#elif defined(MHD_WINSOCK_SOCKETS)
455 if (! SetHandleInformation ((HANDLE)sock, 456 if (! SetHandleInformation ((HANDLE) sock,
456 HANDLE_FLAG_INHERIT, 457 HANDLE_FLAG_INHERIT,
457 0)) 458 0))
458 return 0; 459 return 0;
459#endif /* MHD_WINSOCK_SOCKETS */ 460#endif /* MHD_WINSOCK_SOCKETS */
460 return !0; 461 return ! 0;
461} 462}
462 463
463 464
@@ -508,14 +509,34 @@ MHD_socket_cork_ (MHD_socket sock,
508 const MHD_SCKT_OPT_BOOL_ on_val = 1; 509 const MHD_SCKT_OPT_BOOL_ on_val = 1;
509 510
510 /* Disable extra buffering */ 511 /* Disable extra buffering */
511 return (0 == setsockopt (sock, 512 if (0 != setsockopt (sock,
512 IPPROTO_TCP, 513 IPPROTO_TCP,
513 MHD_TCP_CORK_NOPUSH, 514 MHD_TCP_CORK_NOPUSH,
514 (const void *) (on ? &on_val : &off_val), 515 (const void *) (on ? &on_val : &off_val),
515 sizeof (off_val))); 516 sizeof (off_val)))
517 return 0; /* failed */
518#if defined(__FreeBSD__) && __FreeBSD__ + 0 >= 9
519 /* FreeBSD do not need zero-send for flushing starting from version 9 */
520 return 1;
521#elif defined(TCP_NOPUSH) && ! defined(TCP_CORK)
522 {
523 const int dummy = 0;
524 /* Force flush data with zero send otherwise Darwin and some BSD systems
525 will add 5 seconds delay. Not required with TCP_CORK as switching off
526 TCP_CORK always flushes socket buffer. */
527 if (0 > send (sock,
528 &dummy,
529 0))
530 return 0; /* even force flush failed!? */
531 return 1; /* success */
532 }
516#else 533#else
517 return 0; 534 return 0;
518#endif /* MHD_TCP_CORK_NOPUSH */ 535#endif
536#elif
537 /* do not have MHD_TCP_CORK_NOPUSH at all */
538 return 0;
539#endif
519} 540}
520 541
521 542
@@ -559,7 +580,8 @@ MHD_socket_create_listen_ (int pf)
559 int nosigpipe_set; 580 int nosigpipe_set;
560#endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */ 581#endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */
561 582
562#if defined(MHD_POSIX_SOCKETS) && ( defined(SOCK_CLOEXEC) || defined(SOCK_NOSIGPIPE) ) 583#if defined(MHD_POSIX_SOCKETS) && (defined(SOCK_CLOEXEC) || \
584 defined(SOCK_NOSIGPIPE) )
563 fd = socket (pf, 585 fd = socket (pf,
564 SOCK_STREAM | SOCK_CLOEXEC | MAYBE_SOCK_NOSIGPIPE, 586 SOCK_STREAM | SOCK_CLOEXEC | MAYBE_SOCK_NOSIGPIPE,
565 0); 587 0);
@@ -574,36 +596,36 @@ MHD_socket_create_listen_ (int pf)
574 NULL, 596 NULL,
575 0, 597 0,
576 WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); 598 WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
577 cloexec_set = !0; 599 cloexec_set = ! 0;
578#else /* !SOCK_CLOEXEC */ 600#else /* !SOCK_CLOEXEC */
579 fd = MHD_INVALID_SOCKET; 601 fd = MHD_INVALID_SOCKET;
580#endif /* !SOCK_CLOEXEC */ 602#endif /* !SOCK_CLOEXEC */
581 if (MHD_INVALID_SOCKET == fd) 603 if (MHD_INVALID_SOCKET == fd)
582 { 604 {
583 fd = socket (pf, 605 fd = socket (pf,
584 SOCK_STREAM, 606 SOCK_STREAM,
585 0); 607 0);
586 cloexec_set = 0; 608 cloexec_set = 0;
587 } 609 }
588 if (MHD_INVALID_SOCKET == fd) 610 if (MHD_INVALID_SOCKET == fd)
589 return MHD_INVALID_SOCKET; 611 return MHD_INVALID_SOCKET;
590 612
591#if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_) 613#if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_)
592 if ( ( (! nosigpipe_set) 614 if ( ( (! nosigpipe_set)
593#ifdef MHD_socket_nosignal_ 615#ifdef MHD_socket_nosignal_
594 || (! MHD_socket_nosignal_(fd)) 616 || (! MHD_socket_nosignal_ (fd))
595#endif /* MHD_socket_nosignal_ */ 617#endif /* MHD_socket_nosignal_ */
596 ) && (0 == MAYBE_MSG_NOSIGNAL) ) 618 ) && (0 == MAYBE_MSG_NOSIGNAL) )
597 { 619 {
598 /* SIGPIPE disable is possible on this platform 620 /* SIGPIPE disable is possible on this platform
599 * (so application expect that it will be disabled), 621 * (so application expect that it will be disabled),
600 * but failed to be disabled here and it is not 622 * but failed to be disabled here and it is not
601 * possible to disable SIGPIPE by MSG_NOSIGNAL. */ 623 * possible to disable SIGPIPE by MSG_NOSIGNAL. */
602 const int err = MHD_socket_get_error_ (); 624 const int err = MHD_socket_get_error_ ();
603 (void) MHD_socket_close_ (fd); 625 (void) MHD_socket_close_ (fd);
604 MHD_socket_fset_error_ (err); 626 MHD_socket_fset_error_ (err);
605 return MHD_INVALID_SOCKET; 627 return MHD_INVALID_SOCKET;
606 } 628 }
607#endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */ 629#endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */
608 if (! cloexec_set) 630 if (! cloexec_set)
609 (void) MHD_socket_noninheritable_ (fd); 631 (void) MHD_socket_noninheritable_ (fd);