presumably last touches on ng0's GSoC setsockopt refactoring

This commit is contained in:
Christian Grothoff
2019-10-17 16:52:29 +02:00
parent 63a3681361
commit cbbfd0591f
3 changed files with 152 additions and 189 deletions
+4
View File
@@ -1,3 +1,7 @@
Thu 17 Oct 2019 04:50:52 PM CEST
Integrate 0-byte send() method for uncorking for old FreeBSD/OS X
systems into new mhd_send.c logic for uncorking. -CG
Fri 18 Aug 2019 00:00:00 PM UTC
Fixes and optimizations for the setsockopt handling:
* Added: MHD_UPGRADE_ACTION_CORK_ON and MHD_UPGRADE_ACTION_CORK_OFF
-63
View File
@@ -283,66 +283,6 @@ send_param_adapter (struct MHD_Connection *connection,
}
/**
* Check whether is possible to force push socket buffer content as
* partial packet.
* MHD use different buffering logic depending on whether flushing of
* socket buffer is possible or not.
* If flushing IS possible than MHD activates extra buffering before
* sending data to prevent sending partial packets and flush pending
* data in socket buffer to push last partial packet to client after
* sending logical completed part of data (for example: after sending
* full response header or full response message).
* If flushing IS NOT possible than MHD activates no buffering (no
* delay sending) when it going to send formed fully completed logical
* part of data and activate normal buffering after sending.
* For idled keep-alive connection MHD always activate normal
* buffering.
*
* @param connection connection to check
* @return true if force push is possible, false otherwise
*/
_MHD_static_inline bool
socket_flush_possible (struct MHD_Connection *connection)
{
(void) connection; /* Mute compiler warning. */
#if defined(TCP_CORK) || defined(TCP_PUSH)
return true;
#else /* !TCP_CORK && !TCP_PUSH */
return false;
#endif /* !TCP_CORK && !TCP_PUSH */
}
/**
* Activate no buffering mode (no delay sending) on connection socket
* and push to client data pending in socket buffer.
*
* @param connection connection to be processed
* @return true on success, false otherwise
*/
_MHD_static_inline bool
socket_start_no_buffering_flush (struct MHD_Connection *connection)
{
bool res = false;
#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
const int dummy = 0;
#endif /* !TCP_CORK */
#if defined(__FreeBSD__) && __FreeBSD__ + 0 >= 9
/* FreeBSD do not need zero-send for flushing starting from version 9 */
#elif defined(TCP_NOPUSH) && ! defined(TCP_CORK)
/* Force flush data with zero send otherwise Darwin and some BSD systems
will add 5 seconds delay. Not required with TCP_CORK as switching off
TCP_CORK always flushes socket buffer. */
res = (0 <= MHD_send_ (connection->socket_fd,
&dummy,
0)) && res;
#endif /* TCP_NOPUSH && !TCP_CORK*/
return res;
}
/**
* Get all of the headers from the request.
*
@@ -3593,9 +3533,6 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
break;
case MHD_CONNECTION_HEADERS_SENT:
/* Some clients may take some actions right after header receive */
if (socket_flush_possible (connection))
socket_start_no_buffering_flush (connection); /* REMOVE: Dead */
#ifdef UPGRADE_SUPPORT
if (NULL != connection->response->upgrade_handler)
{
+148 -126
View File
@@ -37,10 +37,10 @@
* @param err the WinSock error code.
* @return pointer to string description of specified WinSock error.
*/
const char* MHD_W32_strerror_winsock_(int err)
const char*MHD_W32_strerror_winsock_ (int err)
{
switch (err)
{
{
case 0:
return "No error";
case WSA_INVALID_HANDLE:
@@ -233,7 +233,7 @@ const char* MHD_W32_strerror_winsock_(int err)
return "Invalid QoS shaping rate object";
case WSA_QOS_RESERVED_PETYPE:
return "Reserved policy QoS element type";
}
}
return "Unknown winsock error";
}
@@ -246,113 +246,114 @@ const char* MHD_W32_strerror_winsock_(int err)
* @return non-zero if succeeded, zero otherwise
*/
int
MHD_W32_socket_pair_(SOCKET sockets_pair[2], int non_blk)
MHD_W32_socket_pair_ (SOCKET sockets_pair[2], int non_blk)
{
int i;
if (! sockets_pair)
{
WSASetLastError (WSAEFAULT);
return 0;
}
{
WSASetLastError (WSAEFAULT);
return 0;
}
#define PAIRMAXTRYIES 800
for (i = 0; i < PAIRMAXTRYIES; i++)
{
struct sockaddr_in listen_addr;
SOCKET listen_s;
static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */
int addr_len = c_addinlen;
unsigned long on_val = 1;
unsigned long off_val = 0;
listen_s = socket (AF_INET,
SOCK_STREAM,
IPPROTO_TCP);
if (INVALID_SOCKET == listen_s)
break; /* can't create even single socket */
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0; /* same as htons(0) */
listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
if ( ((0 == bind (listen_s,
(struct sockaddr*) &listen_addr,
c_addinlen)) &&
(0 == listen (listen_s,
1) ) &&
(0 == getsockname (listen_s,
(struct sockaddr*) &listen_addr,
&addr_len))) )
{
struct sockaddr_in listen_addr;
SOCKET listen_s;
static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */
int addr_len = c_addinlen;
unsigned long on_val = 1;
unsigned long off_val = 0;
SOCKET client_s = socket (AF_INET,
SOCK_STREAM,
IPPROTO_TCP);
struct sockaddr_in accepted_from_addr;
struct sockaddr_in client_addr;
SOCKET server_s;
listen_s = socket (AF_INET,
SOCK_STREAM,
IPPROTO_TCP);
if (INVALID_SOCKET == listen_s)
break; /* can't create even single socket */
if (INVALID_SOCKET == client_s)
{
/* try again */
closesocket (listen_s);
continue;
}
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0; /* same as htons(0) */
listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if ( (0 == bind (listen_s,
(struct sockaddr*) &listen_addr,
c_addinlen) &&
(0 == listen (listen_s,
1) ) &&
(0 == getsockname (listen_s,
(struct sockaddr*) &listen_addr,
&addr_len))) )
{
SOCKET client_s = socket(AF_INET,
SOCK_STREAM,
IPPROTO_TCP);
struct sockaddr_in accepted_from_addr;
struct sockaddr_in client_addr;
SOCKET server_s;
if ( (0 != ioctlsocket (client_s,
FIONBIO,
&on_val)) ||
( (0 != connect (client_s,
(struct sockaddr*) &listen_addr,
c_addinlen)) &&
(WSAGetLastError () != WSAEWOULDBLOCK)) )
{
/* try again */
closesocket (listen_s);
closesocket (client_s);
continue;
}
if (INVALID_SOCKET == client_s)
{
/* try again */
closesocket (listen_s);
continue;
}
addr_len = c_addinlen;
server_s = accept (listen_s,
(struct sockaddr*) &accepted_from_addr,
&addr_len);
if (INVALID_SOCKET == server_s)
{
/* try again */
closesocket (listen_s);
closesocket (client_s);
continue;
}
if ( (0 != ioctlsocket (client_s,
FIONBIO,
&on_val)) ||
( (0 != connect (client_s,
(struct sockaddr*) &listen_addr,
c_addinlen)) &&
(WSAGetLastError() != WSAEWOULDBLOCK)) )
{
/* try again */
closesocket (listen_s);
closesocket (client_s);
continue;
}
addr_len = c_addinlen;
server_s = accept (listen_s,
(struct sockaddr*) &accepted_from_addr,
&addr_len);
if (INVALID_SOCKET == server_s)
{
/* try again */
closesocket (listen_s);
closesocket (client_s);
continue;
}
addr_len = c_addinlen;
if ( (0 == getsockname (client_s,
(struct sockaddr*) &client_addr,
&addr_len)) &&
(accepted_from_addr.sin_family == client_addr.sin_family) &&
(accepted_from_addr.sin_port == client_addr.sin_port) &&
(accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr) &&
( (0 != non_blk) ?
(0 == ioctlsocket(server_s,
FIONBIO,
&on_val)) :
(0 == ioctlsocket(client_s,
FIONBIO,
&off_val)) ) )
{
closesocket (listen_s);
sockets_pair[0] = server_s;
sockets_pair[1] = client_s;
return !0;
}
closesocket (server_s);
closesocket (client_s);
}
closesocket(listen_s);
addr_len = c_addinlen;
if ( (0 == getsockname (client_s,
(struct sockaddr*) &client_addr,
&addr_len)) &&
(accepted_from_addr.sin_family == client_addr.sin_family) &&
(accepted_from_addr.sin_port == client_addr.sin_port) &&
(accepted_from_addr.sin_addr.s_addr ==
client_addr.sin_addr.s_addr) &&
( (0 != non_blk) ?
(0 == ioctlsocket (server_s,
FIONBIO,
&on_val)) :
(0 == ioctlsocket (client_s,
FIONBIO,
&off_val)) ) )
{
closesocket (listen_s);
sockets_pair[0] = server_s;
sockets_pair[1] = client_s;
return ! 0;
}
closesocket (server_s);
closesocket (client_s);
}
closesocket (listen_s);
}
sockets_pair[0] = INVALID_SOCKET;
sockets_pair[1] = INVALID_SOCKET;
WSASetLastError(WSAECONNREFUSED);
WSASetLastError (WSAECONNREFUSED);
return 0;
}
@@ -383,9 +384,9 @@ MHD_add_to_fd_set_ (MHD_socket fd,
set,
fd_setsize))
return 0;
MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_(fd,
set,
fd_setsize);
MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_ (fd,
set,
fd_setsize);
if ( (NULL != max_fd) &&
( (fd > *max_fd) ||
(MHD_INVALID_SOCKET == *max_fd) ) )
@@ -424,7 +425,7 @@ MHD_socket_nonblocking_ (MHD_socket sock)
&flags))
return 0;
#endif /* MHD_WINSOCK_SOCKETS */
return !0;
return ! 0;
}
@@ -452,12 +453,12 @@ MHD_socket_noninheritable_ (MHD_socket sock)
flags | FD_CLOEXEC)) )
return 0;
#elif defined(MHD_WINSOCK_SOCKETS)
if (! SetHandleInformation ((HANDLE)sock,
if (! SetHandleInformation ((HANDLE) sock,
HANDLE_FLAG_INHERIT,
0))
return 0;
#endif /* MHD_WINSOCK_SOCKETS */
return !0;
return ! 0;
}
@@ -508,14 +509,34 @@ MHD_socket_cork_ (MHD_socket sock,
const MHD_SCKT_OPT_BOOL_ on_val = 1;
/* Disable extra buffering */
return (0 == setsockopt (sock,
IPPROTO_TCP,
MHD_TCP_CORK_NOPUSH,
(const void *) (on ? &on_val : &off_val),
sizeof (off_val)));
if (0 != setsockopt (sock,
IPPROTO_TCP,
MHD_TCP_CORK_NOPUSH,
(const void *) (on ? &on_val : &off_val),
sizeof (off_val)))
return 0; /* failed */
#if defined(__FreeBSD__) && __FreeBSD__ + 0 >= 9
/* FreeBSD do not need zero-send for flushing starting from version 9 */
return 1;
#elif defined(TCP_NOPUSH) && ! defined(TCP_CORK)
{
const int dummy = 0;
/* Force flush data with zero send otherwise Darwin and some BSD systems
will add 5 seconds delay. Not required with TCP_CORK as switching off
TCP_CORK always flushes socket buffer. */
if (0 > send (sock,
&dummy,
0))
return 0; /* even force flush failed!? */
return 1; /* success */
}
#else
return 0;
#endif /* MHD_TCP_CORK_NOPUSH */
#endif
#elif
/* do not have MHD_TCP_CORK_NOPUSH at all */
return 0;
#endif
}
@@ -559,7 +580,8 @@ MHD_socket_create_listen_ (int pf)
int nosigpipe_set;
#endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */
#if defined(MHD_POSIX_SOCKETS) && ( defined(SOCK_CLOEXEC) || defined(SOCK_NOSIGPIPE) )
#if defined(MHD_POSIX_SOCKETS) && (defined(SOCK_CLOEXEC) || \
defined(SOCK_NOSIGPIPE) )
fd = socket (pf,
SOCK_STREAM | SOCK_CLOEXEC | MAYBE_SOCK_NOSIGPIPE,
0);
@@ -574,36 +596,36 @@ MHD_socket_create_listen_ (int pf)
NULL,
0,
WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
cloexec_set = !0;
cloexec_set = ! 0;
#else /* !SOCK_CLOEXEC */
fd = MHD_INVALID_SOCKET;
#endif /* !SOCK_CLOEXEC */
if (MHD_INVALID_SOCKET == fd)
{
fd = socket (pf,
SOCK_STREAM,
0);
cloexec_set = 0;
}
{
fd = socket (pf,
SOCK_STREAM,
0);
cloexec_set = 0;
}
if (MHD_INVALID_SOCKET == fd)
return MHD_INVALID_SOCKET;
#if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_)
if ( ( (! nosigpipe_set)
#ifdef MHD_socket_nosignal_
|| (! MHD_socket_nosignal_(fd))
|| (! MHD_socket_nosignal_ (fd))
#endif /* MHD_socket_nosignal_ */
) && (0 == MAYBE_MSG_NOSIGNAL) )
{
/* SIGPIPE disable is possible on this platform
* (so application expect that it will be disabled),
* but failed to be disabled here and it is not
* possible to disable SIGPIPE by MSG_NOSIGNAL. */
const int err = MHD_socket_get_error_ ();
(void) MHD_socket_close_ (fd);
MHD_socket_fset_error_ (err);
return MHD_INVALID_SOCKET;
}
) && (0 == MAYBE_MSG_NOSIGNAL) )
{
/* SIGPIPE disable is possible on this platform
* (so application expect that it will be disabled),
* but failed to be disabled here and it is not
* possible to disable SIGPIPE by MSG_NOSIGNAL. */
const int err = MHD_socket_get_error_ ();
(void) MHD_socket_close_ (fd);
MHD_socket_fset_error_ (err);
return MHD_INVALID_SOCKET;
}
#endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */
if (! cloexec_set)
(void) MHD_socket_noninheritable_ (fd);