libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

mhd_sockets.c (17376B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2014-2024 Karlson2k (Evgeny Grin)
      4 
      5   This library is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU Lesser General Public
      7   License as published by the Free Software Foundation; either
      8   version 2.1 of the License, or (at your option) any later version.
      9 
     10   This library is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library; if not, write to the Free Software
     17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19 */
     20 /**
     21  * @file microhttpd/mhd_sockets.c
     22  * @brief  Implementation for sockets functions
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 #include "mhd_sockets.h"
     26 
     27 #ifdef MHD_WINSOCK_SOCKETS
     28 
     29 /**
     30  * Return pointer to string description of specified WinSock error
     31  * @param err the WinSock error code.
     32  * @return pointer to string description of specified WinSock error.
     33  */
     34 const char *
     35 MHD_W32_strerror_winsock_ (int err)
     36 {
     37   switch (err)
     38   {
     39   case 0:
     40     return "No error";
     41   case WSA_INVALID_HANDLE:
     42     return "Specified event object handle is invalid";
     43   case WSA_NOT_ENOUGH_MEMORY:
     44     return "Insufficient memory available";
     45   case WSA_INVALID_PARAMETER:
     46     return "One or more parameters are invalid";
     47   case WSA_OPERATION_ABORTED:
     48     return "Overlapped operation aborted";
     49   case WSA_IO_INCOMPLETE:
     50     return "Overlapped I/O event object not in signaled state";
     51   case WSA_IO_PENDING:
     52     return "Overlapped operations will complete later";
     53   case WSAEINTR:
     54     return "Interrupted function call";
     55   case WSAEBADF:
     56     return "File handle is not valid";
     57   case WSAEACCES:
     58     return "Permission denied";
     59   case WSAEFAULT:
     60     return "Bad address";
     61   case WSAEINVAL:
     62     return "Invalid argument";
     63   case WSAEMFILE:
     64     return "Too many open files";
     65   case WSAEWOULDBLOCK:
     66     return "Resource temporarily unavailable";
     67   case WSAEINPROGRESS:
     68     return "Operation now in progress";
     69   case WSAEALREADY:
     70     return "Operation already in progress";
     71   case WSAENOTSOCK:
     72     return "Socket operation on nonsocket";
     73   case WSAEDESTADDRREQ:
     74     return "Destination address required";
     75   case WSAEMSGSIZE:
     76     return "Message too long";
     77   case WSAEPROTOTYPE:
     78     return "Protocol wrong type for socket";
     79   case WSAENOPROTOOPT:
     80     return "Bad protocol option";
     81   case WSAEPROTONOSUPPORT:
     82     return "Protocol not supported";
     83   case WSAESOCKTNOSUPPORT:
     84     return "Socket type not supported";
     85   case WSAEOPNOTSUPP:
     86     return "Operation not supported";
     87   case WSAEPFNOSUPPORT:
     88     return "Protocol family not supported";
     89   case WSAEAFNOSUPPORT:
     90     return "Address family not supported by protocol family";
     91   case WSAEADDRINUSE:
     92     return "Address already in use";
     93   case WSAEADDRNOTAVAIL:
     94     return "Cannot assign requested address";
     95   case WSAENETDOWN:
     96     return "Network is down";
     97   case WSAENETUNREACH:
     98     return "Network is unreachable";
     99   case WSAENETRESET:
    100     return "Network dropped connection on reset";
    101   case WSAECONNABORTED:
    102     return "Software caused connection abort";
    103   case WSAECONNRESET:
    104     return "Connection reset by peer";
    105   case WSAENOBUFS:
    106     return "No buffer space available";
    107   case WSAEISCONN:
    108     return "Socket is already connected";
    109   case WSAENOTCONN:
    110     return "Socket is not connected";
    111   case WSAESHUTDOWN:
    112     return "Cannot send after socket shutdown";
    113   case WSAETOOMANYREFS:
    114     return "Too many references";
    115   case WSAETIMEDOUT:
    116     return "Connection timed out";
    117   case WSAECONNREFUSED:
    118     return "Connection refused";
    119   case WSAELOOP:
    120     return "Cannot translate name";
    121   case WSAENAMETOOLONG:
    122     return "Name too long";
    123   case WSAEHOSTDOWN:
    124     return "Host is down";
    125   case WSAEHOSTUNREACH:
    126     return "No route to host";
    127   case WSAENOTEMPTY:
    128     return "Directory not empty";
    129   case WSAEPROCLIM:
    130     return "Too many processes";
    131   case WSAEUSERS:
    132     return "User quota exceeded";
    133   case WSAEDQUOT:
    134     return "Disk quota exceeded";
    135   case WSAESTALE:
    136     return "Stale file handle reference";
    137   case WSAEREMOTE:
    138     return "Item is remote";
    139   case WSASYSNOTREADY:
    140     return "Network subsystem is unavailable";
    141   case WSAVERNOTSUPPORTED:
    142     return "Winsock.dll version out of range";
    143   case WSANOTINITIALISED:
    144     return "Successful WSAStartup not yet performed";
    145   case WSAEDISCON:
    146     return "Graceful shutdown in progress";
    147   case WSAENOMORE:
    148     return "No more results";
    149   case WSAECANCELLED:
    150     return "Call has been canceled";
    151   case WSAEINVALIDPROCTABLE:
    152     return "Procedure call table is invalid";
    153   case WSAEINVALIDPROVIDER:
    154     return "Service provider is invalid";
    155   case WSAEPROVIDERFAILEDINIT:
    156     return "Service provider failed to initialize";
    157   case WSASYSCALLFAILURE:
    158     return "System call failure";
    159   case WSASERVICE_NOT_FOUND:
    160     return "Service not found";
    161   case WSATYPE_NOT_FOUND:
    162     return "Class type not found";
    163   case WSA_E_NO_MORE:
    164     return "No more results";
    165   case WSA_E_CANCELLED:
    166     return "Call was canceled";
    167   case WSAEREFUSED:
    168     return "Database query was refused";
    169   case WSAHOST_NOT_FOUND:
    170     return "Host not found";
    171   case WSATRY_AGAIN:
    172     return "Nonauthoritative host not found";
    173   case WSANO_RECOVERY:
    174     return "This is a nonrecoverable error";
    175   case WSANO_DATA:
    176     return "Valid name, no data record of requested type";
    177   case WSA_QOS_RECEIVERS:
    178     return "QoS receivers";
    179   case WSA_QOS_SENDERS:
    180     return "QoS senders";
    181   case WSA_QOS_NO_SENDERS:
    182     return "No QoS senders";
    183   case WSA_QOS_NO_RECEIVERS:
    184     return "QoS no receivers";
    185   case WSA_QOS_REQUEST_CONFIRMED:
    186     return "QoS request confirmed";
    187   case WSA_QOS_ADMISSION_FAILURE:
    188     return "QoS admission error";
    189   case WSA_QOS_POLICY_FAILURE:
    190     return "QoS policy failure";
    191   case WSA_QOS_BAD_STYLE:
    192     return "QoS bad style";
    193   case WSA_QOS_BAD_OBJECT:
    194     return "QoS bad object";
    195   case WSA_QOS_TRAFFIC_CTRL_ERROR:
    196     return "QoS traffic control error";
    197   case WSA_QOS_GENERIC_ERROR:
    198     return "QoS generic error";
    199   case WSA_QOS_ESERVICETYPE:
    200     return "QoS service type error";
    201   case WSA_QOS_EFLOWSPEC:
    202     return "QoS flowspec error";
    203   case WSA_QOS_EPROVSPECBUF:
    204     return "Invalid QoS provider buffer";
    205   case WSA_QOS_EFILTERSTYLE:
    206     return "Invalid QoS filter style";
    207   case WSA_QOS_EFILTERTYPE:
    208     return "Invalid QoS filter type";
    209   case WSA_QOS_EFILTERCOUNT:
    210     return "Incorrect QoS filter count";
    211   case WSA_QOS_EOBJLENGTH:
    212     return "Invalid QoS object length";
    213   case WSA_QOS_EFLOWCOUNT:
    214     return "Incorrect QoS flow count";
    215   case WSA_QOS_EUNKOWNPSOBJ:
    216     return "Unrecognized QoS object";
    217   case WSA_QOS_EPOLICYOBJ:
    218     return "Invalid QoS policy object";
    219   case WSA_QOS_EFLOWDESC:
    220     return "Invalid QoS flow descriptor";
    221   case WSA_QOS_EPSFLOWSPEC:
    222     return "Invalid QoS provider-specific flowspec";
    223   case WSA_QOS_EPSFILTERSPEC:
    224     return "Invalid QoS provider-specific filterspec";
    225   case WSA_QOS_ESDMODEOBJ:
    226     return "Invalid QoS shape discard mode object";
    227   case WSA_QOS_ESHAPERATEOBJ:
    228     return "Invalid QoS shaping rate object";
    229   case WSA_QOS_RESERVED_PETYPE:
    230     return "Reserved policy QoS element type";
    231   }
    232   return "Unknown winsock error";
    233 }
    234 
    235 
    236 /**
    237  * Create pair of mutually connected TCP/IP sockets on loopback address
    238  * @param sockets_pair array to receive resulted sockets
    239  * @param non_blk if set to non-zero value, sockets created in non-blocking mode
    240  *                otherwise sockets will be in blocking mode
    241  * @return non-zero if succeeded, zero otherwise
    242  */
    243 int
    244 MHD_W32_socket_pair_ (SOCKET sockets_pair[2], int non_blk)
    245 {
    246   int i;
    247 
    248   if (! sockets_pair)
    249   {
    250     WSASetLastError (WSAEFAULT);
    251     return 0;
    252   }
    253 
    254 #define PAIRMAXTRYIES 800
    255   for (i = 0; i < PAIRMAXTRYIES; i++)
    256   {
    257     struct sockaddr_in listen_addr;
    258     SOCKET listen_s;
    259     static const int c_addinlen = sizeof(struct sockaddr_in);   /* help compiler to optimize */
    260     int addr_len = c_addinlen;
    261     unsigned long on_val = 1;
    262     unsigned long off_val = 0;
    263 
    264     listen_s = socket (AF_INET,
    265                        SOCK_STREAM,
    266                        IPPROTO_TCP);
    267     if (INVALID_SOCKET == listen_s)
    268       break;   /* can't create even single socket */
    269 
    270     listen_addr.sin_family = AF_INET;
    271     listen_addr.sin_port = 0;   /* same as htons(0) */
    272     listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    273     if ( ((0 == bind (listen_s,
    274                       (struct sockaddr *) &listen_addr,
    275                       c_addinlen)) &&
    276           (0 == listen (listen_s,
    277                         1) ) &&
    278           (0 == getsockname (listen_s,
    279                              (struct sockaddr *) &listen_addr,
    280                              &addr_len))) )
    281     {
    282       SOCKET client_s = socket (AF_INET,
    283                                 SOCK_STREAM,
    284                                 IPPROTO_TCP);
    285       struct sockaddr_in accepted_from_addr;
    286       struct sockaddr_in client_addr;
    287       SOCKET server_s;
    288 
    289       if (INVALID_SOCKET == client_s)
    290       {
    291         /* try again */
    292         closesocket (listen_s);
    293         continue;
    294       }
    295 
    296       if ( (0 != ioctlsocket (client_s,
    297                               (int) FIONBIO,
    298                               &on_val)) ||
    299            ( (0 != connect (client_s,
    300                             (struct sockaddr *) &listen_addr,
    301                             c_addinlen)) &&
    302              (WSAGetLastError () != WSAEWOULDBLOCK)) )
    303       {
    304         /* try again */
    305         closesocket (listen_s);
    306         closesocket (client_s);
    307         continue;
    308       }
    309 
    310       addr_len = c_addinlen;
    311       server_s = accept (listen_s,
    312                          (struct sockaddr *) &accepted_from_addr,
    313                          &addr_len);
    314       if (INVALID_SOCKET == server_s)
    315       {
    316         /* try again */
    317         closesocket (listen_s);
    318         closesocket (client_s);
    319         continue;
    320       }
    321 
    322       addr_len = c_addinlen;
    323       if ( (0 == getsockname (client_s,
    324                               (struct sockaddr *) &client_addr,
    325                               &addr_len)) &&
    326            (accepted_from_addr.sin_port == client_addr.sin_port) &&
    327            (accepted_from_addr.sin_addr.s_addr ==
    328             client_addr.sin_addr.s_addr) &&
    329            (accepted_from_addr.sin_family == client_addr.sin_family) &&
    330            ( (0 != non_blk) ?
    331              (0 == ioctlsocket (server_s,
    332                                 (int) FIONBIO,
    333                                 &on_val)) :
    334              (0 == ioctlsocket (client_s,
    335                                 (int) FIONBIO,
    336                                 &off_val)) ) &&
    337            (0 == setsockopt (server_s,
    338                              IPPROTO_TCP,
    339                              TCP_NODELAY,
    340                              (const void *) (&on_val),
    341                              sizeof (on_val))) &&
    342            (0 == setsockopt (client_s,
    343                              IPPROTO_TCP,
    344                              TCP_NODELAY,
    345                              (const void *) (&on_val),
    346                              sizeof (on_val))) )
    347       {
    348         closesocket (listen_s);
    349         sockets_pair[0] = server_s;
    350         sockets_pair[1] = client_s;
    351         return ! 0;
    352       }
    353       closesocket (server_s);
    354       closesocket (client_s);
    355     }
    356     closesocket (listen_s);
    357   }
    358 
    359   sockets_pair[0] = INVALID_SOCKET;
    360   sockets_pair[1] = INVALID_SOCKET;
    361   WSASetLastError (WSAECONNREFUSED);
    362 
    363   return 0;
    364 }
    365 
    366 
    367 #endif /* MHD_WINSOCK_SOCKETS */
    368 
    369 
    370 /**
    371  * Add @a fd to the @a set.  If @a fd is
    372  * greater than @a max_fd, set @a max_fd to @a fd.
    373  *
    374  * @param fd file descriptor to add to the @a set
    375  * @param set set to modify
    376  * @param max_fd maximum value to potentially update
    377  * @param fd_setsize value of FD_SETSIZE
    378  * @return non-zero if succeeded, zero otherwise
    379  */
    380 int
    381 MHD_add_to_fd_set_ (MHD_socket fd,
    382                     fd_set *set,
    383                     MHD_socket *max_fd,
    384                     int fd_setsize)
    385 {
    386   if ( (NULL == set) ||
    387        (MHD_INVALID_SOCKET == fd) )
    388     return 0;
    389 
    390 #ifndef HAS_FD_SETSIZE_OVERRIDABLE
    391   (void) fd_setsize;  /* Mute compiler warning */
    392   fd_setsize = (int) FD_SETSIZE; /* Help compiler to optimise */
    393 #endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
    394 
    395   if (! MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (fd,
    396                                          set,
    397                                          fd_setsize))
    398     return 0;
    399   MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_ (fd,
    400                                      set,
    401                                      fd_setsize);
    402   if ( (NULL != max_fd) &&
    403        ( (fd > *max_fd) ||
    404          (MHD_INVALID_SOCKET == *max_fd) ) )
    405     *max_fd = fd;
    406   return ! 0;
    407 }
    408 
    409 
    410 /**
    411  * Change socket options to be non-blocking.
    412  *
    413  * @param sock socket to manipulate
    414  * @return non-zero if succeeded, zero otherwise
    415  */
    416 int
    417 MHD_socket_nonblocking_ (MHD_socket sock)
    418 {
    419 #if defined(MHD_POSIX_SOCKETS)
    420   int flags;
    421 
    422   flags = fcntl (sock,
    423                  F_GETFL);
    424   if (-1 == flags)
    425     return 0;
    426 
    427   if ( ((flags | O_NONBLOCK) != flags) &&
    428        (0 != fcntl (sock,
    429                     F_SETFL,
    430                     flags | O_NONBLOCK)) )
    431     return 0;
    432 #elif defined(MHD_WINSOCK_SOCKETS)
    433   unsigned long flags = 1;
    434 
    435   if (0 != ioctlsocket (sock,
    436                         (int) FIONBIO,
    437                         &flags))
    438     return 0;
    439 #endif /* MHD_WINSOCK_SOCKETS */
    440   return ! 0;
    441 }
    442 
    443 
    444 /**
    445  * Change socket options to be non-inheritable.
    446  *
    447  * @param sock socket to manipulate
    448  * @return non-zero if succeeded, zero otherwise
    449  * @warning Does not set socket error on W32.
    450  */
    451 int
    452 MHD_socket_noninheritable_ (MHD_socket sock)
    453 {
    454 #if defined(MHD_POSIX_SOCKETS)
    455   int flags;
    456 
    457   flags = fcntl (sock,
    458                  F_GETFD);
    459   if (-1 == flags)
    460     return 0;
    461 
    462   if ( ((flags | FD_CLOEXEC) != flags) &&
    463        (0 != fcntl (sock,
    464                     F_SETFD,
    465                     flags | FD_CLOEXEC)) )
    466     return 0;
    467 #elif defined(MHD_WINSOCK_SOCKETS)
    468   if (! SetHandleInformation ((HANDLE) sock,
    469                               HANDLE_FLAG_INHERIT,
    470                               0))
    471     return 0;
    472 #endif /* MHD_WINSOCK_SOCKETS */
    473   return ! 0;
    474 }
    475 
    476 
    477 /**
    478  * Disable Nagle's algorithm on @a sock.  This is what we do by default for
    479  * all TCP sockets in MHD, unless the platform does not support the MSG_MORE
    480  * or MSG_CORK or MSG_NOPUSH options.
    481  *
    482  * @param sock socket to manipulate
    483  * @param on value to use
    484  * @return 0 on success
    485  */
    486 int
    487 MHD_socket_set_nodelay_ (MHD_socket sock,
    488                          bool on)
    489 {
    490 #ifdef TCP_NODELAY
    491   {
    492     const MHD_SCKT_OPT_BOOL_ off_val = 0;
    493     const MHD_SCKT_OPT_BOOL_ on_val = 1;
    494     /* Disable Nagle's algorithm for normal buffering */
    495     return setsockopt (sock,
    496                        IPPROTO_TCP,
    497                        TCP_NODELAY,
    498                        (const void *) ((on) ? &on_val : &off_val),
    499                        sizeof (on_val));
    500   }
    501 #else
    502   (void) sock;
    503   return 0;
    504 #endif /* TCP_NODELAY */
    505 }
    506 
    507 
    508 /**
    509  * Create a listen socket, with noninheritable flag if possible.
    510  *
    511  * @param pf protocol family to use
    512  * @return created socket or MHD_INVALID_SOCKET in case of errors
    513  */
    514 MHD_socket
    515 MHD_socket_create_listen_ (int pf)
    516 {
    517   MHD_socket fd;
    518   int cloexec_set;
    519 #if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_)
    520   int nosigpipe_set;
    521 #endif /* SOCK_NOSIGPIPE ||  MHD_socket_nosignal_ */
    522 
    523 #if defined(MHD_POSIX_SOCKETS) && (defined(SOCK_CLOEXEC) || \
    524   defined(SOCK_NOSIGPIPE) )
    525 
    526   fd = socket (pf,
    527                SOCK_STREAM | SOCK_CLOEXEC | SOCK_NOSIGPIPE_OR_ZERO,
    528                0);
    529   cloexec_set = (SOCK_CLOEXEC_OR_ZERO != 0);
    530 #if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_)
    531   nosigpipe_set = (SOCK_NOSIGPIPE_OR_ZERO != 0);
    532 #endif /* SOCK_NOSIGPIPE ||  MHD_socket_nosignal_ */
    533 #elif defined(MHD_WINSOCK_SOCKETS) && defined(WSA_FLAG_NO_HANDLE_INHERIT)
    534   fd = WSASocketW (pf,
    535                    SOCK_STREAM,
    536                    0,
    537                    NULL,
    538                    0,
    539                    WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
    540   cloexec_set = ! 0;
    541 #else  /* No special socket init function / flags */
    542   fd = MHD_INVALID_SOCKET;
    543   cloexec_set = 0;
    544 #if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_)
    545   nosigpipe_set = 0;
    546 #endif /* SOCK_NOSIGPIPE ||  MHD_socket_nosignal_ */
    547 #endif /* No special socket init function / flags */
    548   if (MHD_INVALID_SOCKET == fd)
    549   {
    550     fd = socket (pf,
    551                  SOCK_STREAM,
    552                  0);
    553     cloexec_set = 0;
    554 #if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_)
    555     nosigpipe_set = 0;
    556 #endif /* SOCK_NOSIGPIPE ||  MHD_socket_nosignal_ */
    557   }
    558   if (MHD_INVALID_SOCKET == fd)
    559     return MHD_INVALID_SOCKET;
    560 
    561 #if defined(MHD_socket_nosignal_)
    562   if ( (! nosigpipe_set) &&
    563        (0 == MHD_socket_nosignal_ (fd)) &&
    564        (0 == MSG_NOSIGNAL_OR_ZERO) )
    565   {
    566     /* SIGPIPE disable is possible on this platform
    567      * (so application expect that it will be disabled),
    568      * but failed to be disabled here and it is not
    569      * possible to disable SIGPIPE by MSG_NOSIGNAL. */
    570     const int err = MHD_socket_get_error_ ();
    571     (void) MHD_socket_close_ (fd);
    572     MHD_socket_fset_error_ (err);
    573     return MHD_INVALID_SOCKET;
    574   }
    575 #endif /* defined(MHD_socket_nosignal_) */
    576   if (! cloexec_set)
    577     (void) MHD_socket_noninheritable_ (fd);
    578 
    579   return fd;
    580 }