|
Packit |
875988 |
/*
|
|
Packit |
875988 |
This file is part of libmicrohttpd
|
|
Packit |
875988 |
Copyright (C) 2014-2016 Karlson2k (Evgeny Grin)
|
|
Packit |
875988 |
|
|
Packit |
875988 |
This library is free software; you can redistribute it and/or
|
|
Packit |
875988 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
875988 |
License as published by the Free Software Foundation; either
|
|
Packit |
875988 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
875988 |
|
|
Packit |
875988 |
This library is distributed in the hope that it will be useful,
|
|
Packit |
875988 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
875988 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
875988 |
Lesser General Public License for more details.
|
|
Packit |
875988 |
|
|
Packit |
875988 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
875988 |
License along with this library; if not, write to the Free Software
|
|
Packit |
875988 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
875988 |
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* @file microhttpd/mhd_sockets.c
|
|
Packit |
875988 |
* @brief Implementation for sockets functions
|
|
Packit |
875988 |
* @author Karlson2k (Evgeny Grin)
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#include "mhd_sockets.h"
|
|
Packit |
875988 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
875988 |
#include <unistd.h>
|
|
Packit |
875988 |
#endif /* HAVE_UNISTD_H */
|
|
Packit |
875988 |
#include <fcntl.h>
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#ifdef MHD_WINSOCK_SOCKETS
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Return pointer to string description of specified WinSock error
|
|
Packit |
875988 |
* @param err the WinSock error code.
|
|
Packit |
875988 |
* @return pointer to string description of specified WinSock error.
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
const char* MHD_W32_strerror_winsock_(int err)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
switch (err)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
case 0:
|
|
Packit |
875988 |
return "No error";
|
|
Packit |
875988 |
case WSA_INVALID_HANDLE:
|
|
Packit |
875988 |
return "Specified event object handle is invalid";
|
|
Packit |
875988 |
case WSA_NOT_ENOUGH_MEMORY:
|
|
Packit |
875988 |
return "Insufficient memory available";
|
|
Packit |
875988 |
case WSA_INVALID_PARAMETER:
|
|
Packit |
875988 |
return "One or more parameters are invalid";
|
|
Packit |
875988 |
case WSA_OPERATION_ABORTED:
|
|
Packit |
875988 |
return "Overlapped operation aborted";
|
|
Packit |
875988 |
case WSA_IO_INCOMPLETE:
|
|
Packit |
875988 |
return "Overlapped I/O event object not in signaled state";
|
|
Packit |
875988 |
case WSA_IO_PENDING:
|
|
Packit |
875988 |
return "Overlapped operations will complete later";
|
|
Packit |
875988 |
case WSAEINTR:
|
|
Packit |
875988 |
return "Interrupted function call";
|
|
Packit |
875988 |
case WSAEBADF:
|
|
Packit |
875988 |
return "File handle is not valid";
|
|
Packit |
875988 |
case WSAEACCES:
|
|
Packit |
875988 |
return "Permission denied";
|
|
Packit |
875988 |
case WSAEFAULT:
|
|
Packit |
875988 |
return "Bad address";
|
|
Packit |
875988 |
case WSAEINVAL:
|
|
Packit |
875988 |
return "Invalid argument";
|
|
Packit |
875988 |
case WSAEMFILE:
|
|
Packit |
875988 |
return "Too many open files";
|
|
Packit |
875988 |
case WSAEWOULDBLOCK:
|
|
Packit |
875988 |
return "Resource temporarily unavailable";
|
|
Packit |
875988 |
case WSAEINPROGRESS:
|
|
Packit |
875988 |
return "Operation now in progress";
|
|
Packit |
875988 |
case WSAEALREADY:
|
|
Packit |
875988 |
return "Operation already in progress";
|
|
Packit |
875988 |
case WSAENOTSOCK:
|
|
Packit |
875988 |
return "Socket operation on nonsocket";
|
|
Packit |
875988 |
case WSAEDESTADDRREQ:
|
|
Packit |
875988 |
return "Destination address required";
|
|
Packit |
875988 |
case WSAEMSGSIZE:
|
|
Packit |
875988 |
return "Message too long";
|
|
Packit |
875988 |
case WSAEPROTOTYPE:
|
|
Packit |
875988 |
return "Protocol wrong type for socket";
|
|
Packit |
875988 |
case WSAENOPROTOOPT:
|
|
Packit |
875988 |
return "Bad protocol option";
|
|
Packit |
875988 |
case WSAEPROTONOSUPPORT:
|
|
Packit |
875988 |
return "Protocol not supported";
|
|
Packit |
875988 |
case WSAESOCKTNOSUPPORT:
|
|
Packit |
875988 |
return "Socket type not supported";
|
|
Packit |
875988 |
case WSAEOPNOTSUPP:
|
|
Packit |
875988 |
return "Operation not supported";
|
|
Packit |
875988 |
case WSAEPFNOSUPPORT:
|
|
Packit |
875988 |
return "Protocol family not supported";
|
|
Packit |
875988 |
case WSAEAFNOSUPPORT:
|
|
Packit |
875988 |
return "Address family not supported by protocol family";
|
|
Packit |
875988 |
case WSAEADDRINUSE:
|
|
Packit |
875988 |
return "Address already in use";
|
|
Packit |
875988 |
case WSAEADDRNOTAVAIL:
|
|
Packit |
875988 |
return "Cannot assign requested address";
|
|
Packit |
875988 |
case WSAENETDOWN:
|
|
Packit |
875988 |
return "Network is down";
|
|
Packit |
875988 |
case WSAENETUNREACH:
|
|
Packit |
875988 |
return "Network is unreachable";
|
|
Packit |
875988 |
case WSAENETRESET:
|
|
Packit |
875988 |
return "Network dropped connection on reset";
|
|
Packit |
875988 |
case WSAECONNABORTED:
|
|
Packit |
875988 |
return "Software caused connection abort";
|
|
Packit |
875988 |
case WSAECONNRESET:
|
|
Packit |
875988 |
return "Connection reset by peer";
|
|
Packit |
875988 |
case WSAENOBUFS:
|
|
Packit |
875988 |
return "No buffer space available";
|
|
Packit |
875988 |
case WSAEISCONN:
|
|
Packit |
875988 |
return "Socket is already connected";
|
|
Packit |
875988 |
case WSAENOTCONN:
|
|
Packit |
875988 |
return "Socket is not connected";
|
|
Packit |
875988 |
case WSAESHUTDOWN:
|
|
Packit |
875988 |
return "Cannot send after socket shutdown";
|
|
Packit |
875988 |
case WSAETOOMANYREFS:
|
|
Packit |
875988 |
return "Too many references";
|
|
Packit |
875988 |
case WSAETIMEDOUT:
|
|
Packit |
875988 |
return "Connection timed out";
|
|
Packit |
875988 |
case WSAECONNREFUSED:
|
|
Packit |
875988 |
return "Connection refused";
|
|
Packit |
875988 |
case WSAELOOP:
|
|
Packit |
875988 |
return "Cannot translate name";
|
|
Packit |
875988 |
case WSAENAMETOOLONG:
|
|
Packit |
875988 |
return "Name too long";
|
|
Packit |
875988 |
case WSAEHOSTDOWN:
|
|
Packit |
875988 |
return "Host is down";
|
|
Packit |
875988 |
case WSAEHOSTUNREACH:
|
|
Packit |
875988 |
return "No route to host";
|
|
Packit |
875988 |
case WSAENOTEMPTY:
|
|
Packit |
875988 |
return "Directory not empty";
|
|
Packit |
875988 |
case WSAEPROCLIM:
|
|
Packit |
875988 |
return "Too many processes";
|
|
Packit |
875988 |
case WSAEUSERS:
|
|
Packit |
875988 |
return "User quota exceeded";
|
|
Packit |
875988 |
case WSAEDQUOT:
|
|
Packit |
875988 |
return "Disk quota exceeded";
|
|
Packit |
875988 |
case WSAESTALE:
|
|
Packit |
875988 |
return "Stale file handle reference";
|
|
Packit |
875988 |
case WSAEREMOTE:
|
|
Packit |
875988 |
return "Item is remote";
|
|
Packit |
875988 |
case WSASYSNOTREADY:
|
|
Packit |
875988 |
return "Network subsystem is unavailable";
|
|
Packit |
875988 |
case WSAVERNOTSUPPORTED:
|
|
Packit |
875988 |
return "Winsock.dll version out of range";
|
|
Packit |
875988 |
case WSANOTINITIALISED:
|
|
Packit |
875988 |
return "Successful WSAStartup not yet performed";
|
|
Packit |
875988 |
case WSAEDISCON:
|
|
Packit |
875988 |
return "Graceful shutdown in progress";
|
|
Packit |
875988 |
case WSAENOMORE:
|
|
Packit |
875988 |
return "No more results";
|
|
Packit |
875988 |
case WSAECANCELLED:
|
|
Packit |
875988 |
return "Call has been canceled";
|
|
Packit |
875988 |
case WSAEINVALIDPROCTABLE:
|
|
Packit |
875988 |
return "Procedure call table is invalid";
|
|
Packit |
875988 |
case WSAEINVALIDPROVIDER:
|
|
Packit |
875988 |
return "Service provider is invalid";
|
|
Packit |
875988 |
case WSAEPROVIDERFAILEDINIT:
|
|
Packit |
875988 |
return "Service provider failed to initialize";
|
|
Packit |
875988 |
case WSASYSCALLFAILURE:
|
|
Packit |
875988 |
return "System call failure";
|
|
Packit |
875988 |
case WSASERVICE_NOT_FOUND:
|
|
Packit |
875988 |
return "Service not found";
|
|
Packit |
875988 |
case WSATYPE_NOT_FOUND:
|
|
Packit |
875988 |
return "Class type not found";
|
|
Packit |
875988 |
case WSA_E_NO_MORE:
|
|
Packit |
875988 |
return "No more results";
|
|
Packit |
875988 |
case WSA_E_CANCELLED:
|
|
Packit |
875988 |
return "Call was canceled";
|
|
Packit |
875988 |
case WSAEREFUSED:
|
|
Packit |
875988 |
return "Database query was refused";
|
|
Packit |
875988 |
case WSAHOST_NOT_FOUND:
|
|
Packit |
875988 |
return "Host not found";
|
|
Packit |
875988 |
case WSATRY_AGAIN:
|
|
Packit |
875988 |
return "Nonauthoritative host not found";
|
|
Packit |
875988 |
case WSANO_RECOVERY:
|
|
Packit |
875988 |
return "This is a nonrecoverable error";
|
|
Packit |
875988 |
case WSANO_DATA:
|
|
Packit |
875988 |
return "Valid name, no data record of requested type";
|
|
Packit |
875988 |
case WSA_QOS_RECEIVERS:
|
|
Packit |
875988 |
return "QoS receivers";
|
|
Packit |
875988 |
case WSA_QOS_SENDERS:
|
|
Packit |
875988 |
return "QoS senders";
|
|
Packit |
875988 |
case WSA_QOS_NO_SENDERS:
|
|
Packit |
875988 |
return "No QoS senders";
|
|
Packit |
875988 |
case WSA_QOS_NO_RECEIVERS:
|
|
Packit |
875988 |
return "QoS no receivers";
|
|
Packit |
875988 |
case WSA_QOS_REQUEST_CONFIRMED:
|
|
Packit |
875988 |
return "QoS request confirmed";
|
|
Packit |
875988 |
case WSA_QOS_ADMISSION_FAILURE:
|
|
Packit |
875988 |
return "QoS admission error";
|
|
Packit |
875988 |
case WSA_QOS_POLICY_FAILURE:
|
|
Packit |
875988 |
return "QoS policy failure";
|
|
Packit |
875988 |
case WSA_QOS_BAD_STYLE:
|
|
Packit |
875988 |
return "QoS bad style";
|
|
Packit |
875988 |
case WSA_QOS_BAD_OBJECT:
|
|
Packit |
875988 |
return "QoS bad object";
|
|
Packit |
875988 |
case WSA_QOS_TRAFFIC_CTRL_ERROR:
|
|
Packit |
875988 |
return "QoS traffic control error";
|
|
Packit |
875988 |
case WSA_QOS_GENERIC_ERROR:
|
|
Packit |
875988 |
return "QoS generic error";
|
|
Packit |
875988 |
case WSA_QOS_ESERVICETYPE:
|
|
Packit |
875988 |
return "QoS service type error";
|
|
Packit |
875988 |
case WSA_QOS_EFLOWSPEC:
|
|
Packit |
875988 |
return "QoS flowspec error";
|
|
Packit |
875988 |
case WSA_QOS_EPROVSPECBUF:
|
|
Packit |
875988 |
return "Invalid QoS provider buffer";
|
|
Packit |
875988 |
case WSA_QOS_EFILTERSTYLE:
|
|
Packit |
875988 |
return "Invalid QoS filter style";
|
|
Packit |
875988 |
case WSA_QOS_EFILTERTYPE:
|
|
Packit |
875988 |
return "Invalid QoS filter type";
|
|
Packit |
875988 |
case WSA_QOS_EFILTERCOUNT:
|
|
Packit |
875988 |
return "Incorrect QoS filter count";
|
|
Packit |
875988 |
case WSA_QOS_EOBJLENGTH:
|
|
Packit |
875988 |
return "Invalid QoS object length";
|
|
Packit |
875988 |
case WSA_QOS_EFLOWCOUNT:
|
|
Packit |
875988 |
return "Incorrect QoS flow count";
|
|
Packit |
875988 |
case WSA_QOS_EUNKOWNPSOBJ:
|
|
Packit |
875988 |
return "Unrecognized QoS object";
|
|
Packit |
875988 |
case WSA_QOS_EPOLICYOBJ:
|
|
Packit |
875988 |
return "Invalid QoS policy object";
|
|
Packit |
875988 |
case WSA_QOS_EFLOWDESC:
|
|
Packit |
875988 |
return "Invalid QoS flow descriptor";
|
|
Packit |
875988 |
case WSA_QOS_EPSFLOWSPEC:
|
|
Packit |
875988 |
return "Invalid QoS provider-specific flowspec";
|
|
Packit |
875988 |
case WSA_QOS_EPSFILTERSPEC:
|
|
Packit |
875988 |
return "Invalid QoS provider-specific filterspec";
|
|
Packit |
875988 |
case WSA_QOS_ESDMODEOBJ:
|
|
Packit |
875988 |
return "Invalid QoS shape discard mode object";
|
|
Packit |
875988 |
case WSA_QOS_ESHAPERATEOBJ:
|
|
Packit |
875988 |
return "Invalid QoS shaping rate object";
|
|
Packit |
875988 |
case WSA_QOS_RESERVED_PETYPE:
|
|
Packit |
875988 |
return "Reserved policy QoS element type";
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
return "Unknown winsock error";
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Create pair of mutually connected TCP/IP sockets on loopback address
|
|
Packit |
875988 |
* @param sockets_pair array to receive resulted sockets
|
|
Packit |
875988 |
* @param non_blk if set to non-zero value, sockets created in non-blocking mode
|
|
Packit |
875988 |
* otherwise sockets will be in blocking mode
|
|
Packit |
875988 |
* @return non-zero if succeeded, zero otherwise
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
int
|
|
Packit |
875988 |
MHD_W32_socket_pair_(SOCKET sockets_pair[2], int non_blk)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
int i;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
if (! sockets_pair)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
WSASetLastError (WSAEFAULT);
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#define PAIRMAXTRYIES 800
|
|
Packit |
875988 |
for (i = 0; i < PAIRMAXTRYIES; i++)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
struct sockaddr_in listen_addr;
|
|
Packit |
875988 |
SOCKET listen_s;
|
|
Packit |
875988 |
static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */
|
|
Packit |
875988 |
int addr_len = c_addinlen;
|
|
Packit |
875988 |
unsigned long on_val = 1;
|
|
Packit |
875988 |
unsigned long off_val = 0;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
listen_s = socket (AF_INET,
|
|
Packit |
875988 |
SOCK_STREAM,
|
|
Packit |
875988 |
IPPROTO_TCP);
|
|
Packit |
875988 |
if (INVALID_SOCKET == listen_s)
|
|
Packit |
875988 |
break; /* can't create even single socket */
|
|
Packit |
875988 |
|
|
Packit |
875988 |
listen_addr.sin_family = AF_INET;
|
|
Packit |
875988 |
listen_addr.sin_port = 0; /* same as htons(0) */
|
|
Packit |
875988 |
listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
Packit |
875988 |
if ( (0 == bind (listen_s,
|
|
Packit |
875988 |
(struct sockaddr*) &listen_addr,
|
|
Packit |
875988 |
c_addinlen) &&
|
|
Packit |
875988 |
(0 == listen (listen_s,
|
|
Packit |
875988 |
1) ) &&
|
|
Packit |
875988 |
(0 == getsockname (listen_s,
|
|
Packit |
875988 |
(struct sockaddr*) &listen_addr,
|
|
Packit |
875988 |
&addr_len))) )
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
SOCKET client_s = socket(AF_INET,
|
|
Packit |
875988 |
SOCK_STREAM,
|
|
Packit |
875988 |
IPPROTO_TCP);
|
|
Packit |
875988 |
struct sockaddr_in accepted_from_addr;
|
|
Packit |
875988 |
struct sockaddr_in client_addr;
|
|
Packit |
875988 |
SOCKET server_s;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
if (INVALID_SOCKET == client_s)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
/* try again */
|
|
Packit |
875988 |
closesocket (listen_s);
|
|
Packit |
875988 |
continue;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
if ( (0 != ioctlsocket (client_s,
|
|
Packit |
875988 |
FIONBIO,
|
|
Packit |
875988 |
&on_val)) ||
|
|
Packit |
875988 |
( (0 != connect (client_s,
|
|
Packit |
875988 |
(struct sockaddr*) &listen_addr,
|
|
Packit |
875988 |
c_addinlen)) &&
|
|
Packit |
875988 |
(WSAGetLastError() != WSAEWOULDBLOCK)) )
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
/* try again */
|
|
Packit |
875988 |
closesocket (listen_s);
|
|
Packit |
875988 |
closesocket (client_s);
|
|
Packit |
875988 |
continue;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
addr_len = c_addinlen;
|
|
Packit |
875988 |
server_s = accept (listen_s,
|
|
Packit |
875988 |
(struct sockaddr*) &accepted_from_addr,
|
|
Packit |
875988 |
&addr_len);
|
|
Packit |
875988 |
if (INVALID_SOCKET == server_s)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
/* try again */
|
|
Packit |
875988 |
closesocket (listen_s);
|
|
Packit |
875988 |
closesocket (client_s);
|
|
Packit |
875988 |
continue;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
addr_len = c_addinlen;
|
|
Packit |
875988 |
if ( (0 == getsockname (client_s,
|
|
Packit |
875988 |
(struct sockaddr*) &client_addr,
|
|
Packit |
875988 |
&addr_len)) &&
|
|
Packit |
875988 |
(accepted_from_addr.sin_family == client_addr.sin_family) &&
|
|
Packit |
875988 |
(accepted_from_addr.sin_port == client_addr.sin_port) &&
|
|
Packit |
875988 |
(accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr) &&
|
|
Packit |
875988 |
( (0 != non_blk) ?
|
|
Packit |
875988 |
(0 == ioctlsocket(server_s,
|
|
Packit |
875988 |
FIONBIO,
|
|
Packit |
875988 |
&on_val)) :
|
|
Packit |
875988 |
(0 == ioctlsocket(client_s,
|
|
Packit |
875988 |
FIONBIO,
|
|
Packit |
875988 |
&off_val)) ) )
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
closesocket (listen_s);
|
|
Packit |
875988 |
sockets_pair[0] = server_s;
|
|
Packit |
875988 |
sockets_pair[1] = client_s;
|
|
Packit |
875988 |
return !0;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
closesocket (server_s);
|
|
Packit |
875988 |
closesocket (client_s);
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
closesocket(listen_s);
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
sockets_pair[0] = INVALID_SOCKET;
|
|
Packit |
875988 |
sockets_pair[1] = INVALID_SOCKET;
|
|
Packit |
875988 |
WSASetLastError(WSAECONNREFUSED);
|
|
Packit |
875988 |
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#endif /* MHD_WINSOCK_SOCKETS */
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Add @a fd to the @a set. If @a fd is
|
|
Packit |
875988 |
* greater than @a max_fd, set @a max_fd to @a fd.
|
|
Packit |
875988 |
*
|
|
Packit |
875988 |
* @param fd file descriptor to add to the @a set
|
|
Packit |
875988 |
* @param set set to modify
|
|
Packit |
875988 |
* @param max_fd maximum value to potentially update
|
|
Packit |
875988 |
* @param fd_setsize value of FD_SETSIZE
|
|
Packit |
875988 |
* @return non-zero if succeeded, zero otherwise
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
int
|
|
Packit |
875988 |
MHD_add_to_fd_set_ (MHD_socket fd,
|
|
Packit |
875988 |
fd_set *set,
|
|
Packit |
875988 |
MHD_socket *max_fd,
|
|
Packit |
875988 |
unsigned int fd_setsize)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
if ( (NULL == set) ||
|
|
Packit |
875988 |
(MHD_INVALID_SOCKET == fd) )
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
if (! MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (fd,
|
|
Packit |
875988 |
set,
|
|
Packit |
875988 |
fd_setsize))
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_(fd,
|
|
Packit |
875988 |
set,
|
|
Packit |
875988 |
fd_setsize);
|
|
Packit |
875988 |
if ( (NULL != max_fd) &&
|
|
Packit |
875988 |
( (fd > *max_fd) ||
|
|
Packit |
875988 |
(MHD_INVALID_SOCKET == *max_fd) ) )
|
|
Packit |
875988 |
*max_fd = fd;
|
|
Packit |
875988 |
return ! 0;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Change socket options to be non-blocking.
|
|
Packit |
875988 |
*
|
|
Packit |
875988 |
* @param sock socket to manipulate
|
|
Packit |
875988 |
* @return non-zero if succeeded, zero otherwise
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
int
|
|
Packit |
875988 |
MHD_socket_nonblocking_ (MHD_socket sock)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
#if defined(MHD_POSIX_SOCKETS)
|
|
Packit |
875988 |
int flags;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
flags = fcntl (sock,
|
|
Packit |
875988 |
F_GETFL);
|
|
Packit |
875988 |
if (-1 == flags)
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
if ( ((flags | O_NONBLOCK) != flags) &&
|
|
Packit |
875988 |
(0 != fcntl (sock,
|
|
Packit |
875988 |
F_SETFL,
|
|
Packit |
875988 |
flags | O_NONBLOCK)) )
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
#elif defined(MHD_WINSOCK_SOCKETS)
|
|
Packit |
875988 |
unsigned long flags = 1;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
if (0 != ioctlsocket (sock,
|
|
Packit |
875988 |
FIONBIO,
|
|
Packit |
875988 |
&flags))
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
#endif /* MHD_WINSOCK_SOCKETS */
|
|
Packit |
875988 |
return !0;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Change socket options to be non-inheritable.
|
|
Packit |
875988 |
*
|
|
Packit |
875988 |
* @param sock socket to manipulate
|
|
Packit |
875988 |
* @return non-zero if succeeded, zero otherwise
|
|
Packit |
875988 |
* @warning Does not set socket error on W32.
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
int
|
|
Packit |
875988 |
MHD_socket_noninheritable_ (MHD_socket sock)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
#if defined(MHD_POSIX_SOCKETS)
|
|
Packit |
875988 |
int flags;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
flags = fcntl (sock,
|
|
Packit |
875988 |
F_GETFD);
|
|
Packit |
875988 |
if (-1 == flags)
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
if ( ((flags | FD_CLOEXEC) != flags) &&
|
|
Packit |
875988 |
(0 != fcntl (sock,
|
|
Packit |
875988 |
F_SETFD,
|
|
Packit |
875988 |
flags | FD_CLOEXEC)) )
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
#elif defined(MHD_WINSOCK_SOCKETS)
|
|
Packit |
875988 |
if (! SetHandleInformation ((HANDLE)sock,
|
|
Packit |
875988 |
HANDLE_FLAG_INHERIT,
|
|
Packit |
875988 |
0))
|
|
Packit |
875988 |
return 0;
|
|
Packit |
875988 |
#endif /* MHD_WINSOCK_SOCKETS */
|
|
Packit |
875988 |
return !0;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Create a listen socket, with noninheritable flag if possible.
|
|
Packit |
875988 |
*
|
|
Packit |
875988 |
* @param use_ipv6 if set to non-zero IPv6 is used
|
|
Packit |
875988 |
* @return created socket or MHD_INVALID_SOCKET in case of errors
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
MHD_socket
|
|
Packit |
875988 |
MHD_socket_create_listen_ (int use_ipv6)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
int domain;
|
|
Packit |
875988 |
MHD_socket fd;
|
|
Packit |
875988 |
int cloexec_set;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#ifdef HAVE_INET6
|
|
Packit |
875988 |
domain = (use_ipv6) ? PF_INET6 : PF_INET;
|
|
Packit |
875988 |
#else /* ! HAVE_INET6 */
|
|
Packit |
875988 |
if (use_ipv6)
|
|
Packit |
875988 |
return MHD_INVALID_SOCKET;
|
|
Packit |
875988 |
domain = PF_INET;
|
|
Packit |
875988 |
#endif /* ! HAVE_INET6 */
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#if defined(MHD_POSIX_SOCKETS) && defined(SOCK_CLOEXEC)
|
|
Packit |
875988 |
fd = socket (domain,
|
|
Packit |
875988 |
SOCK_STREAM | SOCK_CLOEXEC,
|
|
Packit |
875988 |
0);
|
|
Packit |
875988 |
cloexec_set = !0;
|
|
Packit |
875988 |
#elif defined(MHD_WINSOCK_SOCKETS) && defined (WSA_FLAG_NO_HANDLE_INHERIT)
|
|
Packit |
875988 |
fd = WSASocketW (domain,
|
|
Packit |
875988 |
SOCK_STREAM,
|
|
Packit |
875988 |
0,
|
|
Packit |
875988 |
NULL,
|
|
Packit |
875988 |
0,
|
|
Packit |
875988 |
WSA_FLAG_NO_HANDLE_INHERIT);
|
|
Packit |
875988 |
cloexec_set = !0;
|
|
Packit |
875988 |
#else /* !SOCK_CLOEXEC */
|
|
Packit |
875988 |
fd = MHD_INVALID_SOCKET;
|
|
Packit |
875988 |
#endif /* !SOCK_CLOEXEC */
|
|
Packit |
875988 |
if (MHD_INVALID_SOCKET == fd)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
fd = socket (domain,
|
|
Packit |
875988 |
SOCK_STREAM,
|
|
Packit |
875988 |
0);
|
|
Packit |
875988 |
cloexec_set = 0;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
if (MHD_INVALID_SOCKET == fd)
|
|
Packit |
875988 |
return MHD_INVALID_SOCKET;
|
|
Packit |
875988 |
#ifdef MHD_socket_nosignal_
|
|
Packit |
875988 |
if(! MHD_socket_nosignal_(fd))
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
const int err = MHD_socket_get_error_ ();
|
|
Packit |
875988 |
(void) MHD_socket_close_ (fd);
|
|
Packit |
875988 |
MHD_socket_fset_error_ (err);
|
|
Packit |
875988 |
return MHD_INVALID_SOCKET;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
#endif /* MHD_socket_nosignal_ */
|
|
Packit |
875988 |
if (! cloexec_set)
|
|
Packit |
875988 |
(void) MHD_socket_noninheritable_ (fd);
|
|
Packit |
875988 |
|
|
Packit |
875988 |
return fd;
|
|
Packit |
875988 |
}
|