File indexing completed on 2025-01-05 04:37:31

0001 /*
0002     SPDX-FileCopyrightText: 2006 Dan Kennedy.
0003     SPDX-FileCopyrightText: 2006 Juliusz Chroboczek.
0004 
0005     SPDX-License-Identifier: MIT
0006 */
0007 
0008 #include "win32.h"
0009 #include <assert.h>
0010 #include <errno.h>
0011 #include <malloc.h>
0012 // #undef poll
0013 // #undef socket
0014 // #undef connect
0015 // #undef accept
0016 // #undef shutdown
0017 // #undef getpeername
0018 // #undef sleep
0019 // #undef inet_aton
0020 // #undef gettimeofday
0021 // #undef stat
0022 /* Windows needs this header file for the implementation of inet_aton() */
0023 #include <ctype.h>
0024 /*
0025  * Check whether "cp" is a valid ascii representation of an Internet address
0026  * and convert to a binary address.  Returns 1 if the address is valid, 0 if
0027  * not.  This replaces inet_addr, the return value from which cannot
0028  * distinguish between failure and a local broadcast address.
0029  *
0030  * This implementation of the standard inet_aton() function was copied
0031  * (with trivial modifications) from the OpenBSD project.
0032  */
0033 #if 0
0034 int
0035 mingw_inet_aton(const char *cp, struct in_addr *addr)
0036 {
0037     register unsigned int val;
0038     register int base, n;
0039     register char c;
0040     unsigned int parts[4];
0041     register unsigned int *pp = parts;
0042 
0043     assert(sizeof(val) == 4);
0044 
0045     c = *cp;
0046     while (1) {
0047         /*
0048          * Collect number up to ``.''.
0049          * Values are specified as for C:
0050          * 0x=hex, 0=octal, isdigit=decimal.
0051          */
0052         if (!isdigit(c))
0053             return (0);
0054         val = 0; base = 10;
0055         if (c == '0') {
0056             c = *++cp;
0057             if (c == 'x' || c == 'X')
0058                 base = 16, c = *++cp;
0059             else
0060                 base = 8;
0061         }
0062         while (1) {
0063             if (isascii(c) && isdigit(c)) {
0064                 val = (val * base) + (c - '0');
0065                 c = *++cp;
0066             } else if (base == 16 && isascii(c) && isxdigit(c)) {
0067                 val = (val << 4) |
0068                       (c + 10 - (islower(c) ? 'a' : 'A'));
0069                 c = *++cp;
0070             } else
0071                 break;
0072         }
0073         if (c == '.') {
0074             /*
0075              * Internet format:
0076              *    a.b.c.d
0077              *    a.b.c    (with c treated as 16 bits)
0078              *    a.b    (with b treated as 24 bits)
0079              */
0080             if (pp >= parts + 3)
0081                 return (0);
0082             *pp++ = val;
0083             c = *++cp;
0084         } else
0085             break;
0086     }
0087     /*
0088      * Check for trailing characters.
0089      */
0090     if (c != '\0' && (!isascii(c) || !isspace(c)))
0091         return (0);
0092     /*
0093      * Concoct the address according to
0094      * the number of parts specified.
0095      */
0096     n = pp - parts + 1;
0097     switch (n) {
0098 
0099     case 0:
0100         return (0);        /* initial nondigit */
0101 
0102     case 1:                /* a -- 32 bits */
0103         break;
0104 
0105     case 2:                /* a.b -- 8.24 bits */
0106         if ((val > 0xffffff) || (parts[0] > 0xff))
0107             return (0);
0108         val |= parts[0] << 24;
0109         break;
0110 
0111     case 3:                /* a.b.c -- 8.8.16 bits */
0112         if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
0113             return (0);
0114         val |= (parts[0] << 24) | (parts[1] << 16);
0115         break;
0116 
0117     case 4:                /* a.b.c.d -- 8.8.8.8 bits */
0118         if ((val > 0xff) || (parts[0] > 0xff) ||
0119             (parts[1] > 0xff) || (parts[2] > 0xff))
0120             return (0);
0121         val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
0122         break;
0123     }
0124     if (addr)
0125         addr->s_addr = htonl(val);
0126     return (1);
0127 }
0128 
0129 unsigned int
0130 mingw_sleep(unsigned int seconds)
0131 {
0132     Sleep(seconds * 1000);
0133     return 0;
0134 }
0135 
0136 int
0137 mingw_gettimeofday(struct timeval *tv, char *tz)
0138 {
0139     const long long EPOCHFILETIME = (116444736000000000LL);
0140     FILETIME        ft;
0141     LARGE_INTEGER   li;
0142     long long        t;
0143 
0144     /* This implementation doesn't support the timezone parameter. That's Ok,
0145      * as at present polipo always passed NULL as the second arg. We
0146      * also need to make sure that we have at least 8 bytes of space to
0147      * do the math in - otherwise there will be overflow errors.
0148      */
0149     assert(tz == NULL);
0150     assert(sizeof(t) == 8);
0151 
0152     if (tv) {
0153         GetSystemTimeAsFileTime(&ft);
0154         li.LowPart  = ft.dwLowDateTime;
0155         li.HighPart = ft.dwHighDateTime;
0156         t  = li.QuadPart;       /* In 100-nanosecond intervals */
0157         t -= EPOCHFILETIME;     /* Offset to the Epoch time */
0158         t /= 10;                /* In microseconds */
0159         tv->tv_sec  = (long)(t / 1000000);
0160         tv->tv_usec = (long)(t % 1000000);
0161     }
0162     return 0;
0163 }
0164 #endif
0165 
0166 int mingw_poll(struct pollfd *fds, unsigned int nfds, int timo)
0167 {
0168     struct timeval timeout, *toptr;
0169     fd_set ifds, ofds, efds, *ip, *op;
0170     int i, rc;
0171 
0172     /* Set up the file-descriptor sets in ifds, ofds and efds. */
0173     FD_ZERO(&ifds);
0174     FD_ZERO(&ofds);
0175     FD_ZERO(&efds);
0176     for (i = 0, op = ip = 0; i < nfds; ++i) {
0177         fds[i].revents = 0;
0178         if (fds[i].events & (POLLIN | POLLPRI)) {
0179             ip = &ifds;
0180             FD_SET(fds[i].fd, ip);
0181         }
0182         if (fds[i].events & POLLOUT) {
0183             op = &ofds;
0184             FD_SET(fds[i].fd, op);
0185         }
0186         FD_SET(fds[i].fd, &efds);
0187     }
0188 
0189     /* Set up the timeval structure for the timeout parameter */
0190     if (timo < 0) {
0191         toptr = 0;
0192     } else {
0193         toptr = &timeout;
0194         timeout.tv_sec = timo / 1000;
0195         timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
0196     }
0197 
0198     // kWarning()<<QString("Entering select() sec=%1 usec=%2 ip=%3 op=%4").arg(timeout.tv_sec).arg(timeout.tv_usec).arg((long)ip).arg((long)op);
0199 
0200     rc = select(0, ip, op, &efds, toptr);
0201 
0202     // kWarning()<<"Exiting select rc="<<rc;
0203 
0204     if (rc <= 0)
0205         return rc;
0206 
0207     if (rc > 0) {
0208         for (i = 0; i < nfds; ++i) {
0209             int fd = fds[i].fd;
0210             if (fds[i].events & (POLLIN | POLLPRI) && FD_ISSET(fd, &ifds))
0211                 fds[i].revents |= POLLIN;
0212             if (fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
0213                 fds[i].revents |= POLLOUT;
0214             if (FD_ISSET(fd, &efds))
0215                 /* Some error was detected ... should be some way to know. */
0216                 fds[i].revents |= POLLHUP;
0217             // kWarning()<<QString("%1 %2 %3 revent = %4").arg(FD_ISSET(fd, &ifds)).arg(FD_ISSET(fd, &ofds)).arg(FD_ISSET(fd, &efds)).arg(fds[i].revents);
0218         }
0219     }
0220     return rc;
0221 }
0222 #if 0
0223 int mingw_close_socket(SOCKET fd)
0224 {
0225     int rc;
0226 
0227     rc = closesocket(fd);
0228     assert(rc == 0);
0229     return 0;
0230 }
0231 
0232 static void
0233 set_errno(int winsock_err)
0234 {
0235     switch (winsock_err) {
0236     case WSAEWOULDBLOCK:
0237         errno = EAGAIN;
0238         break;
0239     default:
0240         errno = winsock_err;
0241         break;
0242     }
0243 }
0244 
0245 int mingw_write_socket(SOCKET fd, void *buf, int n)
0246 {
0247     int rc = send(fd, buf, n, 0);
0248     if (rc == SOCKET_ERROR) {
0249         set_errno(WSAGetLastError());
0250     }
0251     return rc;
0252 }
0253 
0254 int mingw_read_socket(SOCKET fd, void *buf, int n)
0255 {
0256     int rc = recv(fd, buf, n, 0);
0257     if (rc == SOCKET_ERROR) {
0258         set_errno(WSAGetLastError());
0259     }
0260     return rc;
0261 }
0262 
0263 
0264 /*
0265 * Set the "non-blocking" flag on socket fd to the value specified by
0266 * the second argument (i.e. if the nonblocking argument is non-zero, the
0267 * socket is set to non-blocking mode). Zero is returned if the operation
0268 * is successful, other -1.
0269 */
0270 int
0271 mingw_setnonblocking(SOCKET fd, int nonblocking)
0272 {
0273     int rc;
0274 
0275     unsigned long mode = 1;
0276     rc = ioctlsocket(fd, FIONBIO, &mode);
0277     if (rc != 0) {
0278         set_errno(WSAGetLastError());
0279     }
0280     return (rc == 0 ? 0 : -1);
0281 }
0282 
0283 /*
0284 * A wrapper around the socket() function. The purpose of this wrapper
0285 * is to ensure that the global errno symbol is set if an error occurs,
0286 * even if we are using winsock.
0287 */
0288 SOCKET
0289 mingw_socket(int domain, int type, int protocol)
0290 {
0291     SOCKET fd = socket(domain, type, protocol);
0292     if (fd == INVALID_SOCKET) {
0293         set_errno(WSAGetLastError());
0294     }
0295     return fd;
0296 }
0297 
0298 static void
0299 set_connect_errno(int winsock_err)
0300 {
0301     switch (winsock_err) {
0302     case WSAEINVAL:
0303     case WSAEALREADY:
0304     case WSAEWOULDBLOCK:
0305         errno = EINPROGRESS;
0306         break;
0307     default:
0308         errno = winsock_err;
0309         break;
0310     }
0311 }
0312 
0313 /*
0314 * A wrapper around the connect() function. The purpose of this wrapper
0315 * is to ensure that the global errno symbol is set if an error occurs,
0316 * even if we are using winsock.
0317 */
0318 int
0319 mingw_connect(SOCKET fd, struct sockaddr *addr, socklen_t addr_len)
0320 {
0321     int rc = connect(fd, addr, addr_len);
0322     assert(rc == 0 || rc == SOCKET_ERROR);
0323     if (rc == SOCKET_ERROR) {
0324         set_connect_errno(WSAGetLastError());
0325     }
0326     return rc;
0327 }
0328 
0329 /*
0330 * A wrapper around the accept() function. The purpose of this wrapper
0331 * is to ensure that the global errno symbol is set if an error occurs,
0332 * even if we are using winsock.
0333 */
0334 SOCKET
0335 mingw_accept(SOCKET fd, struct sockaddr *addr, socklen_t *addr_len)
0336 {
0337     SOCKET newfd = accept(fd, addr, addr_len);
0338     if (newfd == INVALID_SOCKET) {
0339         set_errno(WSAGetLastError());
0340         newfd = -1;
0341     }
0342     return newfd;
0343 }
0344 
0345 /*
0346 * A wrapper around the shutdown() function. The purpose of this wrapper
0347 * is to ensure that the global errno symbol is set if an error occurs,
0348 * even if we are using winsock.
0349 */
0350 int
0351 mingw_shutdown(SOCKET fd, int mode)
0352 {
0353     int rc = shutdown(fd, mode);
0354     assert(rc == 0 || rc == SOCKET_ERROR);
0355     if (rc == SOCKET_ERROR) {
0356         set_errno(WSAGetLastError());
0357     }
0358     return rc;
0359 }
0360 
0361 /*
0362 * A wrapper around the getpeername() function. The purpose of this wrapper
0363 * is to ensure that the global errno symbol is set if an error occurs,
0364 * even if we are using winsock.
0365 */
0366 int
0367 mingw_getpeername(SOCKET fd, struct sockaddr *name, socklen_t *namelen)
0368 {
0369     int rc = getpeername(fd, name, namelen);
0370     assert(rc == 0 || rc == SOCKET_ERROR);
0371     if (rc == SOCKET_ERROR) {
0372         set_errno(WSAGetLastError());
0373     }
0374     return rc;
0375 }
0376 
0377 /* Stat doesn't work on directories if the name ends in a slash. */
0378 
0379 int
0380 mingw_stat(const char *filename, struct stat *ss)
0381 {
0382     int len, rc, saved_errno;
0383     char *noslash;
0384 
0385     len = strlen(filename);
0386     if (len <= 1 || filename[len - 1] != '/')
0387         return stat(filename, ss);
0388 
0389     noslash = malloc(len);
0390     if (noslash == NULL)
0391         return -1;
0392 
0393     memcpy(noslash, filename, len - 1);
0394     noslash[len - 1] = '\0';
0395 
0396     rc = stat(noslash, ss);
0397     saved_errno = errno;
0398     free(noslash);
0399     errno = saved_errno;
0400     return rc;
0401 }
0402 #endif
0403 char *mingw_strerror(int error)
0404 {
0405 #ifdef UNICODE
0406     wchar_t message[1024];
0407 #else
0408     char message[1024];
0409 #endif
0410     static char cmessage[1024];
0411 
0412     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0413                   NULL,
0414                   error,
0415                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
0416                   message,
0417                   sizeof(message),
0418                   NULL);
0419 #ifdef UNICODE
0420     wcstombs(cmessage, message, 1024);
0421 #endif
0422     char *p;
0423     for (p = cmessage; *p; p++) {
0424         if (*p == '\n' || *p == '\r')
0425             *p = ' ';
0426     }
0427 
0428     return cmessage;
0429 }
0430 
0431 #if 0
0432 static int init(struct pollfd *pollfds, nfds_t nfds, SOCKET *fds, HANDLE *hEvents)
0433 {
0434     nfds_t i;
0435 
0436     for (i = 0; i < nfds; i++) {
0437         fds[i] = INVALID_SOCKET;
0438         hEvents[i] = NULL;
0439     }
0440 
0441     for (i = 0; i < nfds; i++) {
0442         fds[i] = pollfds[i].fd;
0443         hEvents[i] = WSACreateEvent();
0444         pollfds[i].revents = 0;
0445 
0446         if (WSAEventSelect(fds[i], hEvents[i], pollfds[i].events) < 0) {
0447             errno = WSAGetLastError();
0448             return -1;
0449         }
0450     }
0451 
0452     return 0;
0453 }
0454 
0455 static void clean(nfds_t nfds, SOCKET *fds, HANDLE *hEvents)
0456 {
0457     nfds_t i;
0458 
0459     for (i = 0; i < nfds; i++) {
0460         if (fds[i] != INVALID_SOCKET) {
0461             WSAEventSelect(fds[i], NULL, 0);
0462         }
0463 
0464         if (hEvents[i] != NULL) {
0465             WSACloseEvent(hEvents[i]);
0466         }
0467     }
0468 }
0469 
0470 int poll(struct pollfd *pollfds, nfds_t nfds, int timeout)
0471 {
0472     SOCKET *fds;
0473     HANDLE *hEvents;
0474     DWORD n;
0475 
0476     fds = (SOCKET *)alloca(sizeof(SOCKET) * nfds);
0477     hEvents = (HANDLE *)alloca(sizeof(HANDLE) * nfds);
0478     if (init(pollfds, nfds, fds, hEvents) < 0) {
0479         clean(nfds, fds, hEvents);
0480         return -1;
0481     }
0482 
0483     n = WSAWaitForMultipleEvents(nfds, hEvents, FALSE, timeout, FALSE);
0484     if (n == WSA_WAIT_FAILED) {
0485         clean(nfds, fds, hEvents);
0486         return -1;
0487     } else if (n == WSA_WAIT_TIMEOUT) {
0488         clean(nfds, fds, hEvents);
0489         return 0;
0490     } else {
0491         SOCKET fd;
0492         HANDLE hEvent;
0493         WSANETWORKEVENTS events;
0494 
0495         n -= WSA_WAIT_EVENT_0;
0496         fd = fds[n];
0497         hEvent = hEvents[n];
0498 
0499         if (WSAEnumNetworkEvents(fd, hEvent, &events) < 0) {
0500             clean(nfds, fds, hEvents);
0501             return -1;
0502         }
0503 
0504         pollfds[n].revents = (short) events.lNetworkEvents;
0505         clean(nfds, fds, hEvents);
0506         return n + 1;
0507     }
0508 }
0509 #endif