diff --git a/FIX b/FIX index b617219..08f1452 100644 --- a/FIX +++ b/FIX @@ -1,9 +1,9 @@ +fix bug that caused select return tables not to be associative on windows compiles with g++ new sample unix domain support new sample LPD support comprehensive error messages in the default case. new getstats method to help throttle. -setup error messages in the default case. listen defaults to 32 backlog smtp/ftp/http fail gracefully accept/connect/select interrupt safe diff --git a/TODO b/TODO index 935a409..ec8f25e 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ -test associativity of socket.select - probably if is dirty, no assoc is created. wonder why... +change sock:send to use indices just like string.sub? +use mike's "don't set to blocking before closing unless needed" patch? take a look at DB's smtp patch optmize aux_getgroupudata (Mike idea) @@ -12,7 +12,6 @@ add error message stuff to the manual make sure all modules that can use it actually use socket.newtry adicionar exemplos de expansão: pipe, local, named pipe -Add service name translation. testar os options! - Thread-safe - proteger get*by*.* com um mutex GLOBAL! @@ -29,3 +28,4 @@ testar os options! *use GetSystemTimeAsFileTime in windows (WinCE will suffer document) *add getstats to the manual *Fazer compilar com g++ +*test associativity of socket.select diff --git a/luasocket.vcproj b/luasocket.vcproj index 6700611..f98c72c 100644 --- a/luasocket.vcproj +++ b/luasocket.vcproj @@ -67,13 +67,13 @@ CharacterSet="2"> + DebugInformationFormat="0"/> + DebugInformationFormat="0"/> 0 || (ret == 0 && ndirty > 0)) { + if (ret > 0 || ndirty > 0) { return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); return_fd(L, &wset, max_fd+1, itab, wtab, 0); make_assoc(L, rtab); diff --git a/src/timeout.c b/src/timeout.c index 74ba968..66b98dd 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -192,7 +192,8 @@ int tm_lua_sleep(lua_State *L) struct timespec t, r; t.tv_sec = (int) n; n -= t.tv_sec; - t.tv_nsec = (int) (n * 1000000000) % 1000000000; + t.tv_nsec = (int) (n * 1000000000); + if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; nanosleep(&t, &r); #endif return 0; diff --git a/src/udp.h b/src/udp.h index 0d8e5f4..f34c8ad 100644 --- a/src/udp.h +++ b/src/udp.h @@ -19,7 +19,7 @@ #include "timeout.h" #include "socket.h" -#define UDP_DATAGRAMSIZE 576 +#define UDP_DATAGRAMSIZE 8192 typedef struct t_udp_ { t_sock sock; diff --git a/src/usocket.c b/src/usocket.c index 4d4f092..0cff17b 100644 --- a/src/usocket.c +++ b/src/usocket.c @@ -179,11 +179,11 @@ int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) { int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) { SA daddr; socklen_t dlen = sizeof(daddr); - int err; if (*ps == SOCK_INVALID) return IO_CLOSED; if (!addr) addr = &daddr; if (!len) len = &dlen; for ( ;; ) { + int err; if ((*pa = accept(*ps, addr, len)) != SOCK_INVALID) return IO_DONE; err = errno; if (err == EINTR) continue; @@ -191,7 +191,7 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) { if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; } /* can't reach here */ - return err; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ @@ -223,7 +223,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm) if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; } /* can't reach here */ - return err; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ @@ -247,7 +247,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, if (err != EAGAIN) return err; if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; } - return err; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ @@ -269,7 +269,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) { if (err != EAGAIN) return err; if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; } - return err; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ @@ -292,7 +292,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, if (err != EAGAIN) return err; if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; } - return err; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ @@ -345,10 +345,10 @@ const char *sock_strerror(int err) { switch (err) { case EADDRINUSE: return "eaddrinuse"; case EACCES: return "eaccess"; - case ECONNABORTED: return "econnaborted"; case ECONNREFUSED: return "econnrefused"; - case ECONNRESET: return "econnreset"; - case ETIMEDOUT: return "etimedout"; + case ECONNABORTED: return "closed"; + case ECONNRESET: return "closed"; + case ETIMEDOUT: return "timedout"; default: return strerror(errno); } } diff --git a/src/wsocket.c b/src/wsocket.c index a264452..d9da6fc 100644 --- a/src/wsocket.c +++ b/src/wsocket.c @@ -13,7 +13,6 @@ /* WinSock doesn't have a strerror... */ static const char *wstrerror(int err); -static int wisclosed(int err); /*-------------------------------------------------------------------------*\ * Initializes module @@ -38,15 +37,44 @@ int sock_close(void) { return 1; } +/*-------------------------------------------------------------------------*\ +* Wait for readable/writable/connected socket with timeout +\*-------------------------------------------------------------------------*/ +#define WAITFD_R 1 +#define WAITFD_W 2 +#define WAITFD_E 4 +#define WAITFD_C (WAITFD_E|WAITFD_W) + +static int sock_waitfd(t_sock fd, int sw, p_tm tm) { + int ret; + fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; + struct timeval tv, *tp = NULL; + double t; + if (tm_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ + if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(fd, &rfds); rp = &rfds; } + if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(fd, &wfds); wp = &wfds; } + if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(fd, &efds); ep = &efds; } + if ((t = tm_get(tm)) >= 0.0) { + tv.tv_sec = (int) t; + tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6); + tp = &tv; + } + ret = select(0, rp, wp, ep, tp); + if (ret == -1) return WSAGetLastError(); + if (ret == 0) return IO_TIMEOUT; + if (sw == WAITFD_C && FD_ISSET(fd, &efds)) return IO_CLOSED; + return IO_DONE; +} + /*-------------------------------------------------------------------------*\ * Select with int timeout in ms \*-------------------------------------------------------------------------*/ int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm) { - struct timeval tv; + struct timeval tv; double t = tm_get(tm); tv.tv_sec = (int) t; tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); - return select(n, rfds, wfds, efds, t >= 0.0? &tv: NULL); + return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL); } /*-------------------------------------------------------------------------*\ @@ -72,62 +100,45 @@ void sock_shutdown(p_sock ps, int how) { /*-------------------------------------------------------------------------*\ * Creates and sets up a socket \*-------------------------------------------------------------------------*/ -const char *sock_create(p_sock ps, int domain, int type, int protocol) { - t_sock sock = socket(domain, type, protocol); - if (sock == SOCK_INVALID) return sock_strerror(); - *ps = sock; - return NULL; +int sock_create(p_sock ps, int domain, int type, int protocol) { + *ps = socket(domain, type, protocol); + if (*ps != SOCK_INVALID) return IO_DONE; + else return WSAGetLastError(); } /*-------------------------------------------------------------------------*\ * Connects or returns error message \*-------------------------------------------------------------------------*/ -const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) { - t_sock sock = *ps; +int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) { int err; - fd_set efds, wfds; /* don't call on closed socket */ - if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); + if (*ps == SOCK_INVALID) return IO_CLOSED; /* ask system to connect */ - err = connect(sock, addr, addr_len); - /* if no error, we're done */ - if (err == 0) return NULL; + if (connect(*ps, addr, len) == 0) return IO_DONE; /* make sure the system is trying to connect */ err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) return wstrerror(err); - /* optimize for timeout=0 */ - if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT); - /* wait for a timeout or for the system's answer */ - FD_ZERO(&wfds); FD_SET(sock, &wfds); - FD_ZERO(&efds); FD_SET(sock, &efds); - /* we run select to wait */ - err = sock_select(0, NULL, &wfds, &efds, tm); - /* if select returned due to an event */ - if (err > 0) { - /* if was in efds, we failed */ - if (FD_ISSET(sock, &efds)) { - int why, len = sizeof(why); - /* give windows time to set the error (disgusting) */ - Sleep(0); - /* find out why we failed */ - getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len); - /* we KNOW there was an error. if why is 0, we will return - * "unknown error", but it's not really our fault */ - return wstrerror(why); - /* otherwise it must be in wfds, so we succeeded */ - } else return NULL; - /* if no event happened, we timed out */ - } else if (err == 0) return io_strerror(IO_TIMEOUT); - return sock_strerror(); + if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; + /* we wait until something happens */ + if ((err = sock_waitfd(*ps, WAITFD_C, tm)) == IO_CLOSED) { + int len = sizeof(err); + /* give windows time to set the error (yes, disgusting) */ + Sleep(0); + /* find out why we failed */ + 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; + /* here we deal with the case in which it worked, timedout or weird errors */ + } else return err; } /*-------------------------------------------------------------------------*\ * Binds or returns error message \*-------------------------------------------------------------------------*/ -const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) { - const char *err = NULL; +int sock_bind(p_sock ps, SA *addr, socklen_t len) { + int err = IO_DONE; sock_setblocking(ps); - if (bind(*ps, addr, addr_len) < 0) err = sock_strerror(); + if (bind(*ps, addr, len) < 0) err = WSAGetLastError(); sock_setnonblocking(ps); return err; } @@ -135,10 +146,10 @@ const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) { /*-------------------------------------------------------------------------*\ * \*-------------------------------------------------------------------------*/ -const char *sock_listen(p_sock ps, int backlog) { - const char *err = NULL; +int sock_listen(p_sock ps, int backlog) { + int err = IO_DONE; sock_setblocking(ps); - if (listen(*ps, backlog) < 0) err = sock_strerror(); + if (listen(*ps, backlog) < 0) err = WSAGetLastError(); sock_setnonblocking(ps); return err; } @@ -146,35 +157,25 @@ const char *sock_listen(p_sock ps, int backlog) { /*-------------------------------------------------------------------------*\ * Accept with timeout \*-------------------------------------------------------------------------*/ -const char *sock_accept(p_sock ps, p_sock pa, SA *addr, - socklen_t *addr_len, p_tm tm) { - t_sock sock = *ps; - SA dummy_addr; - socklen_t dummy_len = sizeof(dummy_addr); - if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); - if (!addr) addr = &dummy_addr; - if (!addr_len) addr_len = &dummy_len; - for (;;) { - fd_set rfds; +int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) { + SA daddr; + socklen_t dlen = sizeof(daddr); + if (*ps == SOCK_INVALID) return IO_CLOSED; + if (!addr) addr = &daddr; + if (!len) len = &dlen; + for ( ;; ) { int err; /* try to get client socket */ - *pa = accept(sock, addr, addr_len); - /* if return is valid, we are done */ - if (*pa != SOCK_INVALID) return NULL; - /* otherwise find out why we failed */ + if ((*pa = accept(*ps, addr, len)) != SOCK_INVALID) return IO_DONE; + /* find out why we failed */ err = WSAGetLastError(); /* if we failed because there was no connectoin, keep trying */ - if (err != WSAEWOULDBLOCK) return wstrerror(err); - /* optimize for the timeout=0 case */ - if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT); + if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; /* call select to avoid busy wait */ - FD_ZERO(&rfds); - FD_SET(sock, &rfds); - err = sock_select(0, &rfds, NULL, NULL, tm); - if (err == 0) return io_strerror(IO_TIMEOUT); - else if (err < 0) break; + if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; } - return sock_strerror(); + /* can't reach here */ + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ @@ -182,131 +183,93 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr, \*-------------------------------------------------------------------------*/ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm) { - t_sock sock = *ps; + int err; /* avoid making system calls on closed sockets */ - if (sock == SOCK_INVALID) return IO_CLOSED; + if (*ps == SOCK_INVALID) return IO_CLOSED; + /* loop until we send something or we give up on error */ + *sent = 0; for ( ;; ) { - fd_set fds; - int ret, put; /* try to send something */ - put = send(sock, data, (int) count, 0); + int put = send(*ps, data, (int) count, 0); /* if we sent something, we are done */ if (put > 0) { *sent = put; return IO_DONE; } /* deal with failure */ - *sent = 0; - ret = WSAGetLastError(); - /* check for connection closed */ - if (wisclosed(ret)) return IO_CLOSED; + err = WSAGetLastError(); /* we can only proceed if there was no serious error */ - if (ret != WSAEWOULDBLOCK) return IO_USER; - /* optimize for the timeout = 0 case */ - if (tm_get(tm) == 0.0) return IO_TIMEOUT; - /* run select to avoid busy wait */ - FD_ZERO(&fds); - FD_SET(sock, &fds); - ret = sock_select(0, NULL, &fds, NULL, tm); - if (ret == 0) return IO_TIMEOUT; - else if (ret < 0) break; + if (err != WSAEWOULDBLOCK) return err; + /* avoid busy wait */ + if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; } - return IO_USER; + /* can't reach here */ + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ * Sendto with timeout \*-------------------------------------------------------------------------*/ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, - SA *addr, socklen_t addr_len, p_tm tm) + SA *addr, socklen_t len, p_tm tm) { - t_sock sock = *ps; - /* avoid making system calls on closed sockets */ - if (sock == SOCK_INVALID) return IO_CLOSED; + int err; + if (*ps == SOCK_INVALID) return IO_CLOSED; + *sent = 0; for ( ;; ) { - fd_set fds; - int ret, put; - /* try to send something */ - put = sendto(sock, data, (int) count, 0, addr, addr_len); - /* if we sent something, we are done */ + int put = send(*ps, data, (int) count, 0); if (put > 0) { *sent = put; return IO_DONE; } - /* deal with failure */ - *sent = 0; - ret = WSAGetLastError(); - /* check for connection closed */ - if (wisclosed(ret)) return IO_CLOSED; - /* we can only proceed if there was no serious error */ - if (ret != WSAEWOULDBLOCK) return IO_USER; - /* optimize for the timeout = 0 case */ - if (tm_get(tm) == 0.0) return IO_TIMEOUT; - /* run select to avoid busy wait */ - FD_ZERO(&fds); - FD_SET(sock, &fds); - ret = sock_select(0, NULL, &fds, NULL, tm); - if (ret == 0) return IO_TIMEOUT; - else if (ret < 0) break; + err = WSAGetLastError(); + if (err != WSAEWOULDBLOCK) return err; + if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; } - return IO_USER; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ * Receive with timeout \*-------------------------------------------------------------------------*/ -int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) -{ - t_sock sock = *ps; - if (sock == SOCK_INVALID) return IO_CLOSED; +int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) { + int err; + if (*ps == SOCK_INVALID) return IO_CLOSED; + *got = 0; for ( ;; ) { - fd_set fds; - int ret, taken; - taken = recv(sock, data, (int) count, 0); + int taken = recv(*ps, data, (int) count, 0); if (taken > 0) { *got = taken; return IO_DONE; } - *got = 0; - if (taken == 0 || wisclosed(ret = WSAGetLastError())) return IO_CLOSED; - if (ret != WSAEWOULDBLOCK) return IO_USER; - if (tm_get(tm) == 0.0) return IO_TIMEOUT; - FD_ZERO(&fds); - FD_SET(sock, &fds); - ret = sock_select(0, &fds, NULL, NULL, tm); - if (ret == 0) return IO_TIMEOUT; - else if (ret < 0) break; + if (taken == 0) return IO_CLOSED; + err = WSAGetLastError(); + if (err != WSAEWOULDBLOCK) return err; + if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; } - return IO_TIMEOUT; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ * Recvfrom with timeout \*-------------------------------------------------------------------------*/ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, - SA *addr, socklen_t *addr_len, p_tm tm) -{ - t_sock sock = *ps; - if (sock == SOCK_INVALID) return IO_CLOSED; + SA *addr, socklen_t *len, p_tm tm) { + int err; + if (*ps == SOCK_INVALID) return IO_CLOSED; + *got = 0; for ( ;; ) { - fd_set fds; - int ret, taken; - taken = recvfrom(sock, data, (int) count, 0, addr, addr_len); + int taken = recvfrom(*ps, data, (int) count, 0, addr, len); if (taken > 0) { *got = taken; return IO_DONE; } - *got = 0; - if (taken == 0 || wisclosed(ret = WSAGetLastError())) return IO_CLOSED; - if (ret != WSAEWOULDBLOCK) return IO_USER; - if (tm_get(tm) == 0.0) return IO_TIMEOUT; - FD_ZERO(&fds); - FD_SET(sock, &fds); - ret = sock_select(0, &fds, NULL, NULL, tm); - if (ret == 0) return IO_TIMEOUT; - else if (ret < 0) break; + if (taken == 0) return IO_CLOSED; + err = WSAGetLastError(); + if (err != WSAEWOULDBLOCK) return err; + if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; } - return IO_TIMEOUT; + return IO_UNKNOWN; } /*-------------------------------------------------------------------------*\ @@ -325,139 +288,97 @@ void sock_setnonblocking(p_sock ps) { ioctlsocket(*ps, FIONBIO, &argp); } +/*-------------------------------------------------------------------------*\ +* DNS helpers +\*-------------------------------------------------------------------------*/ +int sock_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { + *hp = gethostbyaddr(addr, len, AF_INET); + if (*hp) return IO_DONE; + else return h_errno; +} + +int sock_gethostbyname(const char *addr, struct hostent **hp) { + *hp = gethostbyname(addr); + if (*hp) return IO_DONE; + else return h_errno; +} + /*-------------------------------------------------------------------------*\ * Error translation functions \*-------------------------------------------------------------------------*/ -const char *sock_hoststrerror(void) { - int err = WSAGetLastError(); +const char *sock_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 "host_not_found"; + default: return wstrerror(err); } } -const char *sock_strerror(void) { - int err = WSAGetLastError(); +const char *sock_strerror(int err) { + if (err <= 0) return io_strerror(err); switch (err) { - case WSAEADDRINUSE: - return "address already in use"; - default: - return wstrerror(err); + case WSAEADDRINUSE: return "eaddrinuse"; + case WSAECONNREFUSED: return "econnrefused"; + case WSAECONNABORTED: return "closed"; + case WSAECONNRESET: return "closed"; + case WSAETIMEDOUT: return "timeout"; + default: return wstrerror(err); } } -const char *sock_geterr(p_sock ps, int code) { - (void) ps; - (void) code; - return sock_strerror(); -} - -int wisclosed(int err) { - switch (err) { - case WSAECONNRESET: - case WSAECONNABORTED: - case WSAESHUTDOWN: - case WSAENOTCONN: - return 1; - default: - return 0; - } +const char *sock_ioerror(p_sock ps, int err) { + (void) ps; + return sock_strerror(err); } static const char *wstrerror(int err) { switch (err) { - case WSAEINTR: - return "WSAEINTR: Interrupted function call"; - case WSAEACCES: - return "WSAEACCES: Permission denied"; - case WSAEFAULT: - return "WSAEFAULT: Bad address"; - case WSAEINVAL: - return "WSAEINVAL: Invalid argument"; - case WSAEMFILE: - return "WSAEMFILE: Too many open files"; - case WSAEWOULDBLOCK: - return "WSAEWOULDBLOCK: Resource temporarily unavailable"; - case WSAEINPROGRESS: - return "WSAEINPROGRESS: Operation now in progress"; - case WSAEALREADY: - return "WSAEALREADY: Operation already in progress"; - case WSAENOTSOCK: - return "WSAENOTSOCK: Socket operation on nonsocket"; - case WSAEDESTADDRREQ: - return "WSAEDESTADDRREQ: Destination address required"; - case WSAEMSGSIZE: - return "WSAEMSGSIZE: Message too long"; - case WSAEPROTOTYPE: - return "WSAEPROTOTYPE: Protocol wrong type for socket"; - case WSAENOPROTOOPT: - return "WSAENOPROTOOPT: Bad protocol option"; - case WSAEPROTONOSUPPORT: - return "WSAEPROTONOSUPPORT: Protocol not supported"; - case WSAESOCKTNOSUPPORT: - return "WSAESOCKTNOSUPPORT: Socket type not supported"; - case WSAEOPNOTSUPP: - return "WSAEOPNOTSUPP: Operation not supported"; - case WSAEPFNOSUPPORT: - return "WSAEPFNOSUPPORT: Protocol family not supported"; - case WSAEAFNOSUPPORT: - return "WSAEAFNOSUPPORT: Address family not supported by " - "protocol family"; - case WSAEADDRINUSE: - return "WSAEADDRINUSE: Address already in use"; - case WSAEADDRNOTAVAIL: - return "WSAEADDRNOTAVAIL: Cannot assign requested address"; - case WSAENETDOWN: - return "WSAENETDOWN: Network is down"; - case WSAENETUNREACH: - return "WSAENETUNREACH: Network is unreachable"; - case WSAENETRESET: - return "WSAENETRESET: Network dropped connection on reset"; - case WSAECONNABORTED: - return "WSAECONNABORTED: Software caused connection abort"; - case WSAECONNRESET: - return "WSAECONNRESET: Connection reset by peer"; - case WSAENOBUFS: - return "WSAENOBUFS: No buffer space available"; - case WSAEISCONN: - return "WSAEISCONN: Socket is already connected"; - case WSAENOTCONN: - return "WSAENOTCONN: Socket is not connected"; - case WSAESHUTDOWN: - return "WSAESHUTDOWN: Cannot send after socket shutdown"; - case WSAETIMEDOUT: - return "WSAETIMEDOUT: Connection timed out"; - case WSAECONNREFUSED: - return "WSAECONNREFUSED: Connection refused"; - case WSAEHOSTDOWN: - return "WSAEHOSTDOWN: Host is down"; - case WSAEHOSTUNREACH: - return "WSAEHOSTUNREACH: No route to host"; - case WSAEPROCLIM: - return "WSAEPROCLIM: Too many processes"; - case WSASYSNOTREADY: - return "WSASYSNOTREADY: Network subsystem is unavailable"; - case WSAVERNOTSUPPORTED: - return "WSAVERNOTSUPPORTED: Winsock.dll version out of range"; - case WSANOTINITIALISED: - return "WSANOTINITIALISED: Successful WSAStartup not yet performed"; - case WSAEDISCON: - return "WSAEDISCON: Graceful shutdown in progress"; - case WSATYPE_NOT_FOUND: - return "WSATYPE_NOT_FOUND: Class type not found"; - case WSAHOST_NOT_FOUND: - return "WSAHOST_NOT_FOUND: Host not found"; - case WSATRY_AGAIN: - return "WSATRY_AGAIN: Nonauthoritative host not found"; - case WSANO_RECOVERY: - return "WSANO_RECOVERY: Nonrecoverable name lookup error"; - case WSANO_DATA: - return "WSANO_DATA: Valid name, no data record of requested type"; - case WSASYSCALLFAILURE: - return "WSASYSCALLFAILURE: System call failure"; - default: - return "Unknown error"; + case WSAEINTR: return "Interrupted function call"; + case WSAEACCES: return "Permission denied"; + case WSAEFAULT: return "Bad address"; + case WSAEINVAL: return "Invalid argument"; + case WSAEMFILE: return "Too many open files"; + case WSAEWOULDBLOCK: return "Resource temporarily unavailable"; + case WSAEINPROGRESS: return "Operation now in progress"; + case WSAEALREADY: return "Operation already in progress"; + case WSAENOTSOCK: return "Socket operation on nonsocket"; + case WSAEDESTADDRREQ: return "Destination address required"; + case WSAEMSGSIZE: return "Message too long"; + 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 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 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 WSAENOBUFS: return "No buffer space available"; + case WSAEISCONN: return "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 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: + return "Successful WSAStartup not yet performed"; + case WSAEDISCON: return "Graceful shutdown in progress"; + case WSATYPE_NOT_FOUND: return "Class type not found"; + case WSAHOST_NOT_FOUND: return "Host not found"; + case WSATRY_AGAIN: return "Nonauthoritative host not found"; + case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; + case WSANO_DATA: return "Valid name, no data record of requested type"; + case WSASYSCALLFAILURE: return "System call failure"; + default: return "Unknown error"; } } diff --git a/test/testclnt.lua b/test/testclnt.lua index a1fd805..f98a504 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua @@ -283,7 +283,9 @@ function empty_connect() if not data then pass("ok") data = socket.connect(host, port) - else fail("should not have connected!") end + else + pass("gethostbyname returns localhost on empty string...") + end end ------------------------------------------------------------------------ @@ -374,19 +376,17 @@ end ------------------------------------------------------------------------ function connect_timeout() - io.stderr:write("connect with timeout (if it hangs, it failed): ") + io.stderr:write("connect with timeout (if it hangs, it failed!): ") local t = socket.gettime() local c, e = socket.tcp() assert(c, e) c:settimeout(0.1) - ip = socket.dns.toip("ibere.tecgraf.puc-rio.br") - if not ip then return end local t = socket.gettime() - local r, e = c:connect(ip, 80) + local r, e = c:connect("127.0.0.2", 80) assert(not r, "should not connect") - --assert(e == "timeout", e) assert(socket.gettime() - t < 2, "took too long to give up.") c:close() + print("ok") end ------------------------------------------------------------------------