diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luasocket/src/wsocket.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luasocket/src/wsocket.c | 156 |
1 files changed, 88 insertions, 68 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luasocket/src/wsocket.c b/Build/source/texk/web2c/luatexdir/luasocket/src/wsocket.c index d6dd004e7e2..8ecb0fc7a8e 100644 --- a/Build/source/texk/web2c/luatexdir/luasocket/src/wsocket.c +++ b/Build/source/texk/web2c/luatexdir/luasocket/src/wsocket.c @@ -3,33 +3,34 @@ * LuaSocket toolkit * * The penalty of calling select to avoid busy-wait is only paid when -* the I/O call fail in the first place. +* the I/O call fail in the first place. \*=========================================================================*/ #include <string.h> #include "socket.h" +#include "pierror.h" /* WinSock doesn't have a strerror... */ static const char *wstrerror(int err); /*-------------------------------------------------------------------------*\ -* Initializes module +* Initializes module \*-------------------------------------------------------------------------*/ int socket_open(void) { WSADATA wsaData; - WORD wVersionRequested = MAKEWORD(2, 0); + WORD wVersionRequested = MAKEWORD(2, 0); int err = WSAStartup(wVersionRequested, &wsaData ); if (err != 0) return 0; if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { WSACleanup(); - return 0; + return 0; } return 1; } /*-------------------------------------------------------------------------*\ -* Close module +* Close module \*-------------------------------------------------------------------------*/ int socket_close(void) { WSACleanup(); @@ -50,10 +51,10 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { struct timeval tv, *tp = NULL; double t; if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ - if (sw & WAITFD_R) { - FD_ZERO(&rfds); + if (sw & WAITFD_R) { + FD_ZERO(&rfds); FD_SET(*ps, &rfds); - rp = &rfds; + rp = &rfds; } if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } @@ -72,9 +73,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { /*-------------------------------------------------------------------------*\ * Select with int timeout in ms \*-------------------------------------------------------------------------*/ -int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, +int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_timeout tm) { - struct timeval tv; + struct timeval tv; double t = timeout_get(tm); tv.tv_sec = (int) t; tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); @@ -96,7 +97,7 @@ void socket_destroy(p_socket ps) { } /*-------------------------------------------------------------------------*\ -* +* \*-------------------------------------------------------------------------*/ void socket_shutdown(p_socket ps, int how) { socket_setblocking(ps); @@ -134,10 +135,10 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { /* give windows time to set the error (yes, disgusting) */ Sleep(10); /* find out why we failed */ - getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); + getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); /* we KNOW there was an error. if 'why' is 0, we will return * "unknown error", but it's not really our fault */ - return err > 0? err: IO_UNKNOWN; + return err > 0? err: IO_UNKNOWN; } else return err; } @@ -154,7 +155,7 @@ int socket_bind(p_socket ps, SA *addr, socklen_t len) { } /*-------------------------------------------------------------------------*\ -* +* \*-------------------------------------------------------------------------*/ int socket_listen(p_socket ps, int backlog) { int err = IO_DONE; @@ -167,7 +168,7 @@ int socket_listen(p_socket ps, int backlog) { /*-------------------------------------------------------------------------*\ * Accept with timeout \*-------------------------------------------------------------------------*/ -int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, +int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { @@ -175,21 +176,21 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, /* try to get client socket */ if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; /* find out why we failed */ - err = WSAGetLastError(); + err = WSAGetLastError(); /* if we failed because there was no connectoin, keep trying */ if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; /* call select to avoid busy wait */ if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } + } } /*-------------------------------------------------------------------------*\ * Send with timeout -* On windows, if you try to send 10MB, the OS will buffer EVERYTHING -* this can take an awful lot of time and we will end up blocked. +* On windows, if you try to send 10MB, the OS will buffer EVERYTHING +* this can take an awful lot of time and we will end up blocked. * Therefore, whoever calls this function should not pass a huge buffer. \*-------------------------------------------------------------------------*/ -int socket_send(p_socket ps, const char *data, size_t count, +int socket_send(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm) { int err; @@ -206,18 +207,18 @@ int socket_send(p_socket ps, const char *data, size_t count, return IO_DONE; } /* deal with failure */ - err = WSAGetLastError(); + err = WSAGetLastError(); /* we can only proceed if there was no serious error */ if (err != WSAEWOULDBLOCK) return err; /* avoid busy wait */ if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } + } } /*-------------------------------------------------------------------------*\ * Sendto with timeout \*-------------------------------------------------------------------------*/ -int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, +int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, SA *addr, socklen_t len, p_timeout tm) { int err; @@ -229,17 +230,19 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, *sent = put; return IO_DONE; } - err = WSAGetLastError(); + err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) return err; if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } + } } /*-------------------------------------------------------------------------*\ * Receive with timeout \*-------------------------------------------------------------------------*/ -int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { - int err; +int socket_recv(p_socket ps, char *data, size_t count, size_t *got, + p_timeout tm) +{ + int err, prev = IO_DONE; *got = 0; if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { @@ -250,7 +253,14 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm } if (taken == 0) return IO_CLOSED; err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) return err; + /* On UDP, a connreset simply means the previous send failed. + * So we try again. + * On TCP, it means our socket is now useless, so the error passes. + * (We will loop again, exiting because the same error will happen) */ + if (err != WSAEWOULDBLOCK) { + if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; + prev = err; + } if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; } } @@ -258,9 +268,10 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm /*-------------------------------------------------------------------------*\ * Recvfrom with timeout \*-------------------------------------------------------------------------*/ -int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, - SA *addr, socklen_t *len, p_timeout tm) { - int err; +int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, + SA *addr, socklen_t *len, p_timeout tm) +{ + int err, prev = IO_DONE; *got = 0; if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { @@ -271,7 +282,14 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, } if (taken == 0) return IO_CLOSED; err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) return err; + /* On UDP, a connreset simply means the previous send failed. + * So we try again. + * On TCP, it means our socket is now useless, so the error passes. + * (We will loop again, exiting because the same error will happen) */ + if (err != WSAEWOULDBLOCK) { + if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; + prev = err; + } if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; } } @@ -293,7 +311,7 @@ void socket_setnonblocking(p_socket ps) { } /*-------------------------------------------------------------------------*\ -* DNS helpers +* DNS helpers \*-------------------------------------------------------------------------*/ int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { *hp = gethostbyaddr(addr, len, AF_INET); @@ -313,21 +331,21 @@ int socket_gethostbyname(const char *addr, struct hostent **hp) { const char *socket_hoststrerror(int err) { if (err <= 0) return io_strerror(err); switch (err) { - case WSAHOST_NOT_FOUND: return "host not found"; - default: return wstrerror(err); + case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; + default: return wstrerror(err); } } const char *socket_strerror(int err) { if (err <= 0) return io_strerror(err); switch (err) { - case WSAEADDRINUSE: return "address already in use"; - case WSAECONNREFUSED: return "connection refused"; - case WSAEISCONN: return "already connected"; - case WSAEACCES: return "permission denied"; - case WSAECONNABORTED: return "closed"; - case WSAECONNRESET: return "closed"; - case WSAETIMEDOUT: return "timeout"; + case WSAEADDRINUSE: return PIE_ADDRINUSE; + case WSAECONNREFUSED : return PIE_CONNREFUSED; + case WSAEISCONN: return PIE_ISCONN; + case WSAEACCES: return PIE_ACCESS; + case WSAECONNABORTED: return PIE_CONNABORTED; + case WSAECONNRESET: return PIE_CONNRESET; + case WSAETIMEDOUT: return PIE_TIMEDOUT; default: return wstrerror(err); } } @@ -340,7 +358,7 @@ const char *socket_ioerror(p_socket ps, int err) { static const char *wstrerror(int err) { switch (err) { case WSAEINTR: return "Interrupted function call"; - case WSAEACCES: return "Permission denied"; + case WSAEACCES: return PIE_ACCESS; // "Permission denied"; case WSAEFAULT: return "Bad address"; case WSAEINVAL: return "Invalid argument"; case WSAEMFILE: return "Too many open files"; @@ -353,60 +371,62 @@ static const char *wstrerror(int err) { case WSAEPROTOTYPE: return "Protocol wrong type for socket"; case WSAENOPROTOOPT: return "Bad protocol option"; case WSAEPROTONOSUPPORT: return "Protocol not supported"; - case WSAESOCKTNOSUPPORT: return "Socket type not supported"; + case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; case WSAEOPNOTSUPP: return "Operation not supported"; case WSAEPFNOSUPPORT: return "Protocol family not supported"; - case WSAEAFNOSUPPORT: - return "Address family not supported by protocol family"; - case WSAEADDRINUSE: return "Address already in use"; + case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; + case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; case WSAENETDOWN: return "Network is down"; case WSAENETUNREACH: return "Network is unreachable"; case WSAENETRESET: return "Network dropped connection on reset"; case WSAECONNABORTED: return "Software caused connection abort"; - case WSAECONNRESET: return "Connection reset by peer"; + case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer"; case WSAENOBUFS: return "No buffer space available"; - case WSAEISCONN: return "Socket is already connected"; + case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected"; case WSAENOTCONN: return "Socket is not connected"; case WSAESHUTDOWN: return "Cannot send after socket shutdown"; - case WSAETIMEDOUT: return "Connection timed out"; - case WSAECONNREFUSED: return "Connection refused"; + case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out"; + case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused"; case WSAEHOSTDOWN: return "Host is down"; case WSAEHOSTUNREACH: return "No route to host"; case WSAEPROCLIM: return "Too many processes"; case WSASYSNOTREADY: return "Network subsystem is unavailable"; case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; - case WSANOTINITIALISED: + case WSANOTINITIALISED: return "Successful WSAStartup not yet performed"; case WSAEDISCON: return "Graceful shutdown in progress"; - case WSAHOST_NOT_FOUND: return "Host not found"; + case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; case WSATRY_AGAIN: return "Nonauthoritative host not found"; - case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; + case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; case WSANO_DATA: return "Valid name, no data record of requested type"; default: return "Unknown error"; } } const char *socket_gaistrerror(int err) { - if (err == 0) return NULL; + if (err == 0) return NULL; switch (err) { - case EAI_AGAIN: return "temporary failure in name resolution"; - case EAI_BADFLAGS: return "invalid value for ai_flags"; + case EAI_AGAIN: return PIE_AGAIN; + case EAI_BADFLAGS: return PIE_BADFLAGS; #ifdef EAI_BADHINTS - case EAI_BADHINTS: return "invalid value for hints"; + case EAI_BADHINTS: return PIE_BADHINTS; +#endif + case EAI_FAIL: return PIE_FAIL; + case EAI_FAMILY: return PIE_FAMILY; + case EAI_MEMORY: return PIE_MEMORY; + case EAI_NONAME: return PIE_NONAME; +#ifdef EAI_OVERFLOW + case EAI_OVERFLOW: return PIE_OVERFLOW; #endif - case EAI_FAIL: return "non-recoverable failure in name resolution"; - case EAI_FAMILY: return "ai_family not supported"; - case EAI_MEMORY: return "memory allocation failure"; - case EAI_NONAME: - return "host or service not provided, or not known"; -// case EAI_OVERFLOW: return "argument buffer overflow"; #ifdef EAI_PROTOCOL - case EAI_PROTOCOL: return "resolved protocol is unknown"; + case EAI_PROTOCOL: return PIE_PROTOCOL; +#endif + case EAI_SERVICE: return PIE_SERVICE; + case EAI_SOCKTYPE: return PIE_SOCKTYPE; +#ifdef EAI_SYSTEM + case EAI_SYSTEM: return strerror(errno); #endif - case EAI_SERVICE: return "service not supported for socket type"; - case EAI_SOCKTYPE: return "ai_socktype not supported"; -// case EAI_SYSTEM: return strerror(errno); default: return gai_strerror(err); } } |