mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
presumably last touches on ng0's GSoC setsockopt refactoring
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user