aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-07-16 06:48:48 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-07-16 06:48:48 +0000
commite4e2223cff658a7016724a625ebbd3dacb92a8f9 (patch)
treeaac49c61149d30bf11219ab8d9989915bf7bee37
parent9a79d500eb3e015f5bf579aab714916d49c1f289 (diff)
downloadluasocket-e4e2223cff658a7016724a625ebbd3dacb92a8f9.tar.gz
luasocket-e4e2223cff658a7016724a625ebbd3dacb92a8f9.tar.bz2
luasocket-e4e2223cff658a7016724a625ebbd3dacb92a8f9.zip
Fixed a bunch of stuff. Added mike's patches.
-rw-r--r--FIX2
-rw-r--r--TODO6
-rw-r--r--luasocket.vcproj4
-rw-r--r--mime.vcproj4
-rw-r--r--samples/listener.lua50
-rw-r--r--src/inet.c7
-rw-r--r--src/io.h13
-rw-r--r--src/select.c2
-rw-r--r--src/timeout.c3
-rw-r--r--src/udp.h2
-rw-r--r--src/usocket.c18
-rw-r--r--src/wsocket.c453
-rw-r--r--test/testclnt.lua12
13 files changed, 249 insertions, 327 deletions
diff --git a/FIX b/FIX
index b617219..08f1452 100644
--- a/FIX
+++ b/FIX
@@ -1,9 +1,9 @@
1fix bug that caused select return tables not to be associative on windows
1compiles with g++ 2compiles with g++
2new sample unix domain support 3new sample unix domain support
3new sample LPD support 4new sample LPD support
4comprehensive error messages in the default case. 5comprehensive error messages in the default case.
5new getstats method to help throttle. 6new getstats method to help throttle.
6setup error messages in the default case.
7listen defaults to 32 backlog 7listen defaults to 32 backlog
8smtp/ftp/http fail gracefully 8smtp/ftp/http fail gracefully
9accept/connect/select interrupt safe 9accept/connect/select interrupt safe
diff --git a/TODO b/TODO
index 935a409..ec8f25e 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,6 @@
1test associativity of socket.select
2 probably if is dirty, no assoc is created. wonder why...
3 1
2change sock:send to use indices just like string.sub?
3use mike's "don't set to blocking before closing unless needed" patch?
4take a look at DB's smtp patch 4take a look at DB's smtp patch
5 5
6optmize aux_getgroupudata (Mike idea) 6optmize aux_getgroupudata (Mike idea)
@@ -12,7 +12,6 @@ add error message stuff to the manual
12 12
13make sure all modules that can use it actually use socket.newtry 13make sure all modules that can use it actually use socket.newtry
14adicionar exemplos de expansão: pipe, local, named pipe 14adicionar exemplos de expansão: pipe, local, named pipe
15Add service name translation.
16testar os options! 15testar os options!
17- Thread-safe 16- Thread-safe
18 - proteger get*by*.* com um mutex GLOBAL! 17 - proteger get*by*.* com um mutex GLOBAL!
@@ -29,3 +28,4 @@ testar os options!
29 *use GetSystemTimeAsFileTime in windows (WinCE will suffer document) 28 *use GetSystemTimeAsFileTime in windows (WinCE will suffer document)
30*add getstats to the manual 29*add getstats to the manual
31*Fazer compilar com g++ 30*Fazer compilar com g++
31*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 @@
67 CharacterSet="2"> 67 CharacterSet="2">
68 <Tool 68 <Tool
69 Name="VCCLCompilerTool" 69 Name="VCCLCompilerTool"
70 AdditionalIncludeDirectories="H:\include" 70 AdditionalIncludeDirectories="../../include"
71 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport); LUASOCKET_DEBUG" 71 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport); LUASOCKET_DEBUG"
72 RuntimeLibrary="0" 72 RuntimeLibrary="0"
73 UsePrecompiledHeader="0" 73 UsePrecompiledHeader="0"
74 WarningLevel="3" 74 WarningLevel="3"
75 Detect64BitPortabilityProblems="TRUE" 75 Detect64BitPortabilityProblems="TRUE"
76 DebugInformationFormat="3"/> 76 DebugInformationFormat="0"/>
77 <Tool 77 <Tool
78 Name="VCCustomBuildTool"/> 78 Name="VCCustomBuildTool"/>
79 <Tool 79 <Tool
diff --git a/mime.vcproj b/mime.vcproj
index 95d3888..6e5ae36 100644
--- a/mime.vcproj
+++ b/mime.vcproj
@@ -67,13 +67,13 @@
67 CharacterSet="2"> 67 CharacterSet="2">
68 <Tool 68 <Tool
69 Name="VCCLCompilerTool" 69 Name="VCCLCompilerTool"
70 AdditionalIncludeDirectories="H:\include" 70 AdditionalIncludeDirectories="../../include"
71 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS; MIME_API=__declspec(dllexport)" 71 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS; MIME_API=__declspec(dllexport)"
72 RuntimeLibrary="0" 72 RuntimeLibrary="0"
73 UsePrecompiledHeader="0" 73 UsePrecompiledHeader="0"
74 WarningLevel="3" 74 WarningLevel="3"
75 Detect64BitPortabilityProblems="TRUE" 75 Detect64BitPortabilityProblems="TRUE"
76 DebugInformationFormat="3"/> 76 DebugInformationFormat="0"/>
77 <Tool 77 <Tool
78 Name="VCCustomBuildTool"/> 78 Name="VCCustomBuildTool"/>
79 <Tool 79 <Tool
diff --git a/samples/listener.lua b/samples/listener.lua
index b2f7a7e..65c6501 100644
--- a/samples/listener.lua
+++ b/samples/listener.lua
@@ -1,25 +1,25 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- TCP sample: Little program to dump lines received at a given port 2-- TCP sample: Little program to dump lines received at a given port
3-- LuaSocket sample files 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
7local socket = require("socket") 7local socket = require("socket")
8host = host or "*" 8host = host or "*"
9port = port or 8080 9port = port or 8080
10if arg then 10if arg then
11 host = arg[1] or host 11 host = arg[1] or host
12 port = arg[2] or port 12 port = arg[2] or port
13end 13end
14print("Binding to host '" ..host.. "' and port " ..port.. "...") 14print("Binding to host '" ..host.. "' and port " ..port.. "...")
15s = socket.try(socket.bind(host, port)) 15s = socket.try(socket.bind(host, port))
16i, p = socket.try(s:getsockname()) 16i, p = socket.try(s:getsockname())
17print("Waiting connection from talker on " .. i .. ":" .. p .. "...") 17print("Waiting connection from talker on " .. i .. ":" .. p .. "...")
18c = socket.try(s:accept()) 18c = socket.try(s:accept())
19print("Connected. Here is the stuff:") 19print("Connected. Here is the stuff:")
20l, e = c:receive() 20l, e = c:receive()
21while not e do 21while not e do
22 print(l) 22 print(l)
23 l, e = c:receive() 23 l, e = c:receive()
24end 24end
25print(e) 25print(e)
diff --git a/src/inet.c b/src/inet.c
index 33191c3..e2afcdf 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -209,8 +209,8 @@ const char *inet_tryconnect(p_sock ps, const char *address,
209 memset(&remote, 0, sizeof(remote)); 209 memset(&remote, 0, sizeof(remote));
210 remote.sin_family = AF_INET; 210 remote.sin_family = AF_INET;
211 remote.sin_port = htons(port); 211 remote.sin_port = htons(port);
212 if (strcmp(address, "*")) { 212 if (strcmp(address, "*")) {
213 if (!strlen(address) || !inet_aton(address, &remote.sin_addr)) { 213 if (!inet_aton(address, &remote.sin_addr)) {
214 struct hostent *hp = NULL; 214 struct hostent *hp = NULL;
215 struct in_addr **addr; 215 struct in_addr **addr;
216 err = sock_gethostbyname(address, &hp); 216 err = sock_gethostbyname(address, &hp);
@@ -236,8 +236,7 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port)
236 local.sin_addr.s_addr = htonl(INADDR_ANY); 236 local.sin_addr.s_addr = htonl(INADDR_ANY);
237 local.sin_port = htons(port); 237 local.sin_port = htons(port);
238 local.sin_family = AF_INET; 238 local.sin_family = AF_INET;
239 if (strcmp(address, "*") && 239 if (strcmp(address, "*") && !inet_aton(address, &local.sin_addr)) {
240 (!strlen(address) || !inet_aton(address, &local.sin_addr))) {
241 struct hostent *hp = NULL; 240 struct hostent *hp = NULL;
242 struct in_addr **addr; 241 struct in_addr **addr;
243 err = sock_gethostbyname(address, &hp); 242 err = sock_gethostbyname(address, &hp);
diff --git a/src/io.h b/src/io.h
index 22cf467..51801f6 100644
--- a/src/io.h
+++ b/src/io.h
@@ -24,18 +24,19 @@ enum {
24 IO_DONE = 0, /* operation completed successfully */ 24 IO_DONE = 0, /* operation completed successfully */
25 IO_TIMEOUT = -1, /* operation timed out */ 25 IO_TIMEOUT = -1, /* operation timed out */
26 IO_CLOSED = -2, /* the connection has been closed */ 26 IO_CLOSED = -2, /* the connection has been closed */
27 IO_CLIPPED = -3 /* maxium bytes count reached */ 27 IO_CLIPPED = -3, /* maxium bytes count reached */
28 IO_UNKNOWN = -4
28}; 29};
29 30
30/* interface to error message function */ 31/* interface to error message function */
31typedef const char *(*p_error) ( 32typedef const char *(*p_error) (
32 void *ctx, /* context needed by send */ 33 void *ctx, /* context needed by send */
33 int err /* error code */ 34 int err /* error code */
34); 35);
35 36
36/* interface to send function */ 37/* interface to send function */
37typedef int (*p_send) ( 38typedef int (*p_send) (
38 void *ctx, /* context needed by send */ 39 void *ctx, /* context needed by send */
39 const char *data, /* pointer to buffer with data to send */ 40 const char *data, /* pointer to buffer with data to send */
40 size_t count, /* number of bytes to send from buffer */ 41 size_t count, /* number of bytes to send from buffer */
41 size_t *sent, /* number of bytes sent uppon return */ 42 size_t *sent, /* number of bytes sent uppon return */
@@ -44,7 +45,7 @@ typedef int (*p_send) (
44 45
45/* interface to recv function */ 46/* interface to recv function */
46typedef int (*p_recv) ( 47typedef int (*p_recv) (
47 void *ctx, /* context needed by recv */ 48 void *ctx, /* context needed by recv */
48 char *data, /* pointer to buffer where data will be writen */ 49 char *data, /* pointer to buffer where data will be writen */
49 size_t count, /* number of bytes to receive into buffer */ 50 size_t count, /* number of bytes to receive into buffer */
50 size_t *got, /* number of bytes received uppon return */ 51 size_t *got, /* number of bytes received uppon return */
@@ -61,6 +62,6 @@ typedef struct t_io_ {
61typedef t_io *p_io; 62typedef t_io *p_io;
62 63
63void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); 64void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx);
64const char *io_strerror(int err); 65const char *io_strerror(int err);
65 66
66#endif /* IO_H */ 67#endif /* IO_H */ \ No newline at end of file
diff --git a/src/select.c b/src/select.c
index 3c01b06..a92a2c5 100644
--- a/src/select.c
+++ b/src/select.c
@@ -64,7 +64,7 @@ static int global_select(lua_State *L) {
64 tm_init(&tm, t, -1); 64 tm_init(&tm, t, -1);
65 max_fd = collect_fd(L, 2, max_fd, itab, &wset); 65 max_fd = collect_fd(L, 2, max_fd, itab, &wset);
66 ret = sock_select(max_fd+1, &rset, &wset, NULL, &tm); 66 ret = sock_select(max_fd+1, &rset, &wset, NULL, &tm);
67 if (ret > 0 || (ret == 0 && ndirty > 0)) { 67 if (ret > 0 || ndirty > 0) {
68 return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); 68 return_fd(L, &rset, max_fd+1, itab, rtab, ndirty);
69 return_fd(L, &wset, max_fd+1, itab, wtab, 0); 69 return_fd(L, &wset, max_fd+1, itab, wtab, 0);
70 make_assoc(L, rtab); 70 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)
192 struct timespec t, r; 192 struct timespec t, r;
193 t.tv_sec = (int) n; 193 t.tv_sec = (int) n;
194 n -= t.tv_sec; 194 n -= t.tv_sec;
195 t.tv_nsec = (int) (n * 1000000000) % 1000000000; 195 t.tv_nsec = (int) (n * 1000000000);
196 if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
196 nanosleep(&t, &r); 197 nanosleep(&t, &r);
197#endif 198#endif
198 return 0; 199 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 @@
19#include "timeout.h" 19#include "timeout.h"
20#include "socket.h" 20#include "socket.h"
21 21
22#define UDP_DATAGRAMSIZE 576 22#define UDP_DATAGRAMSIZE 8192
23 23
24typedef struct t_udp_ { 24typedef struct t_udp_ {
25 t_sock sock; 25 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) {
179int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) { 179int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) {
180 SA daddr; 180 SA daddr;
181 socklen_t dlen = sizeof(daddr); 181 socklen_t dlen = sizeof(daddr);
182 int err;
183 if (*ps == SOCK_INVALID) return IO_CLOSED; 182 if (*ps == SOCK_INVALID) return IO_CLOSED;
184 if (!addr) addr = &daddr; 183 if (!addr) addr = &daddr;
185 if (!len) len = &dlen; 184 if (!len) len = &dlen;
186 for ( ;; ) { 185 for ( ;; ) {
186 int err;
187 if ((*pa = accept(*ps, addr, len)) != SOCK_INVALID) return IO_DONE; 187 if ((*pa = accept(*ps, addr, len)) != SOCK_INVALID) return IO_DONE;
188 err = errno; 188 err = errno;
189 if (err == EINTR) continue; 189 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) {
191 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 191 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err;
192 } 192 }
193 /* can't reach here */ 193 /* can't reach here */
194 return err; 194 return IO_UNKNOWN;
195} 195}
196 196
197/*-------------------------------------------------------------------------*\ 197/*-------------------------------------------------------------------------*\
@@ -223,7 +223,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
223 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; 223 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err;
224 } 224 }
225 /* can't reach here */ 225 /* can't reach here */
226 return err; 226 return IO_UNKNOWN;
227} 227}
228 228
229/*-------------------------------------------------------------------------*\ 229/*-------------------------------------------------------------------------*\
@@ -247,7 +247,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
247 if (err != EAGAIN) return err; 247 if (err != EAGAIN) return err;
248 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err; 248 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err;
249 } 249 }
250 return err; 250 return IO_UNKNOWN;
251} 251}
252 252
253/*-------------------------------------------------------------------------*\ 253/*-------------------------------------------------------------------------*\
@@ -269,7 +269,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) {
269 if (err != EAGAIN) return err; 269 if (err != EAGAIN) return err;
270 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 270 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err;
271 } 271 }
272 return err; 272 return IO_UNKNOWN;
273} 273}
274 274
275/*-------------------------------------------------------------------------*\ 275/*-------------------------------------------------------------------------*\
@@ -292,7 +292,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
292 if (err != EAGAIN) return err; 292 if (err != EAGAIN) return err;
293 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err; 293 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err;
294 } 294 }
295 return err; 295 return IO_UNKNOWN;
296} 296}
297 297
298/*-------------------------------------------------------------------------*\ 298/*-------------------------------------------------------------------------*\
@@ -345,10 +345,10 @@ const char *sock_strerror(int err) {
345 switch (err) { 345 switch (err) {
346 case EADDRINUSE: return "eaddrinuse"; 346 case EADDRINUSE: return "eaddrinuse";
347 case EACCES: return "eaccess"; 347 case EACCES: return "eaccess";
348 case ECONNABORTED: return "econnaborted";
349 case ECONNREFUSED: return "econnrefused"; 348 case ECONNREFUSED: return "econnrefused";
350 case ECONNRESET: return "econnreset"; 349 case ECONNABORTED: return "closed";
351 case ETIMEDOUT: return "etimedout"; 350 case ECONNRESET: return "closed";
351 case ETIMEDOUT: return "timedout";
352 default: return strerror(errno); 352 default: return strerror(errno);
353 } 353 }
354} 354}
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 @@
13 13
14/* WinSock doesn't have a strerror... */ 14/* WinSock doesn't have a strerror... */
15static const char *wstrerror(int err); 15static const char *wstrerror(int err);
16static int wisclosed(int err);
17 16
18/*-------------------------------------------------------------------------*\ 17/*-------------------------------------------------------------------------*\
19* Initializes module 18* Initializes module
@@ -39,14 +38,43 @@ int sock_close(void) {
39} 38}
40 39
41/*-------------------------------------------------------------------------*\ 40/*-------------------------------------------------------------------------*\
41* Wait for readable/writable/connected socket with timeout
42\*-------------------------------------------------------------------------*/
43#define WAITFD_R 1
44#define WAITFD_W 2
45#define WAITFD_E 4
46#define WAITFD_C (WAITFD_E|WAITFD_W)
47
48static int sock_waitfd(t_sock fd, int sw, p_tm tm) {
49 int ret;
50 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
51 struct timeval tv, *tp = NULL;
52 double t;
53 if (tm_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
54 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(fd, &rfds); rp = &rfds; }
55 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(fd, &wfds); wp = &wfds; }
56 if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(fd, &efds); ep = &efds; }
57 if ((t = tm_get(tm)) >= 0.0) {
58 tv.tv_sec = (int) t;
59 tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6);
60 tp = &tv;
61 }
62 ret = select(0, rp, wp, ep, tp);
63 if (ret == -1) return WSAGetLastError();
64 if (ret == 0) return IO_TIMEOUT;
65 if (sw == WAITFD_C && FD_ISSET(fd, &efds)) return IO_CLOSED;
66 return IO_DONE;
67}
68
69/*-------------------------------------------------------------------------*\
42* Select with int timeout in ms 70* Select with int timeout in ms
43\*-------------------------------------------------------------------------*/ 71\*-------------------------------------------------------------------------*/
44int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm) { 72int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm) {
45 struct timeval tv; 73 struct timeval tv;
46 double t = tm_get(tm); 74 double t = tm_get(tm);
47 tv.tv_sec = (int) t; 75 tv.tv_sec = (int) t;
48 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); 76 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
49 return select(n, rfds, wfds, efds, t >= 0.0? &tv: NULL); 77 return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL);
50} 78}
51 79
52/*-------------------------------------------------------------------------*\ 80/*-------------------------------------------------------------------------*\
@@ -72,62 +100,45 @@ void sock_shutdown(p_sock ps, int how) {
72/*-------------------------------------------------------------------------*\ 100/*-------------------------------------------------------------------------*\
73* Creates and sets up a socket 101* Creates and sets up a socket
74\*-------------------------------------------------------------------------*/ 102\*-------------------------------------------------------------------------*/
75const char *sock_create(p_sock ps, int domain, int type, int protocol) { 103int sock_create(p_sock ps, int domain, int type, int protocol) {
76 t_sock sock = socket(domain, type, protocol); 104 *ps = socket(domain, type, protocol);
77 if (sock == SOCK_INVALID) return sock_strerror(); 105 if (*ps != SOCK_INVALID) return IO_DONE;
78 *ps = sock; 106 else return WSAGetLastError();
79 return NULL;
80} 107}
81 108
82/*-------------------------------------------------------------------------*\ 109/*-------------------------------------------------------------------------*\
83* Connects or returns error message 110* Connects or returns error message
84\*-------------------------------------------------------------------------*/ 111\*-------------------------------------------------------------------------*/
85const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) { 112int sock_connect(p_sock ps, SA *addr, socklen_t len, p_tm tm) {
86 t_sock sock = *ps;
87 int err; 113 int err;
88 fd_set efds, wfds;
89 /* don't call on closed socket */ 114 /* don't call on closed socket */
90 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); 115 if (*ps == SOCK_INVALID) return IO_CLOSED;
91 /* ask system to connect */ 116 /* ask system to connect */
92 err = connect(sock, addr, addr_len); 117 if (connect(*ps, addr, len) == 0) return IO_DONE;
93 /* if no error, we're done */
94 if (err == 0) return NULL;
95 /* make sure the system is trying to connect */ 118 /* make sure the system is trying to connect */
96 err = WSAGetLastError(); 119 err = WSAGetLastError();
97 if (err != WSAEWOULDBLOCK) return wstrerror(err); 120 if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err;
98 /* optimize for timeout=0 */ 121 /* we wait until something happens */
99 if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT); 122 if ((err = sock_waitfd(*ps, WAITFD_C, tm)) == IO_CLOSED) {
100 /* wait for a timeout or for the system's answer */ 123 int len = sizeof(err);
101 FD_ZERO(&wfds); FD_SET(sock, &wfds); 124 /* give windows time to set the error (yes, disgusting) */
102 FD_ZERO(&efds); FD_SET(sock, &efds); 125 Sleep(0);
103 /* we run select to wait */ 126 /* find out why we failed */
104 err = sock_select(0, NULL, &wfds, &efds, tm); 127 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
105 /* if select returned due to an event */ 128 /* we KNOW there was an error. if why is 0, we will return
106 if (err > 0) { 129 * "unknown error", but it's not really our fault */
107 /* if was in efds, we failed */ 130 return err > 0? err: IO_UNKNOWN;
108 if (FD_ISSET(sock, &efds)) { 131 /* here we deal with the case in which it worked, timedout or weird errors */
109 int why, len = sizeof(why); 132 } else return err;
110 /* give windows time to set the error (disgusting) */
111 Sleep(0);
112 /* find out why we failed */
113 getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len);
114 /* we KNOW there was an error. if why is 0, we will return
115 * "unknown error", but it's not really our fault */
116 return wstrerror(why);
117 /* otherwise it must be in wfds, so we succeeded */
118 } else return NULL;
119 /* if no event happened, we timed out */
120 } else if (err == 0) return io_strerror(IO_TIMEOUT);
121 return sock_strerror();
122} 133}
123 134
124/*-------------------------------------------------------------------------*\ 135/*-------------------------------------------------------------------------*\
125* Binds or returns error message 136* Binds or returns error message
126\*-------------------------------------------------------------------------*/ 137\*-------------------------------------------------------------------------*/
127const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) { 138int sock_bind(p_sock ps, SA *addr, socklen_t len) {
128 const char *err = NULL; 139 int err = IO_DONE;
129 sock_setblocking(ps); 140 sock_setblocking(ps);
130 if (bind(*ps, addr, addr_len) < 0) err = sock_strerror(); 141 if (bind(*ps, addr, len) < 0) err = WSAGetLastError();
131 sock_setnonblocking(ps); 142 sock_setnonblocking(ps);
132 return err; 143 return err;
133} 144}
@@ -135,10 +146,10 @@ const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) {
135/*-------------------------------------------------------------------------*\ 146/*-------------------------------------------------------------------------*\
136* 147*
137\*-------------------------------------------------------------------------*/ 148\*-------------------------------------------------------------------------*/
138const char *sock_listen(p_sock ps, int backlog) { 149int sock_listen(p_sock ps, int backlog) {
139 const char *err = NULL; 150 int err = IO_DONE;
140 sock_setblocking(ps); 151 sock_setblocking(ps);
141 if (listen(*ps, backlog) < 0) err = sock_strerror(); 152 if (listen(*ps, backlog) < 0) err = WSAGetLastError();
142 sock_setnonblocking(ps); 153 sock_setnonblocking(ps);
143 return err; 154 return err;
144} 155}
@@ -146,35 +157,25 @@ const char *sock_listen(p_sock ps, int backlog) {
146/*-------------------------------------------------------------------------*\ 157/*-------------------------------------------------------------------------*\
147* Accept with timeout 158* Accept with timeout
148\*-------------------------------------------------------------------------*/ 159\*-------------------------------------------------------------------------*/
149const char *sock_accept(p_sock ps, p_sock pa, SA *addr, 160int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *len, p_tm tm) {
150 socklen_t *addr_len, p_tm tm) { 161 SA daddr;
151 t_sock sock = *ps; 162 socklen_t dlen = sizeof(daddr);
152 SA dummy_addr; 163 if (*ps == SOCK_INVALID) return IO_CLOSED;
153 socklen_t dummy_len = sizeof(dummy_addr); 164 if (!addr) addr = &daddr;
154 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); 165 if (!len) len = &dlen;
155 if (!addr) addr = &dummy_addr; 166 for ( ;; ) {
156 if (!addr_len) addr_len = &dummy_len;
157 for (;;) {
158 fd_set rfds;
159 int err; 167 int err;
160 /* try to get client socket */ 168 /* try to get client socket */
161 *pa = accept(sock, addr, addr_len); 169 if ((*pa = accept(*ps, addr, len)) != SOCK_INVALID) return IO_DONE;
162 /* if return is valid, we are done */ 170 /* find out why we failed */
163 if (*pa != SOCK_INVALID) return NULL;
164 /* otherwise find out why we failed */
165 err = WSAGetLastError(); 171 err = WSAGetLastError();
166 /* if we failed because there was no connectoin, keep trying */ 172 /* if we failed because there was no connectoin, keep trying */
167 if (err != WSAEWOULDBLOCK) return wstrerror(err); 173 if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
168 /* optimize for the timeout=0 case */
169 if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT);
170 /* call select to avoid busy wait */ 174 /* call select to avoid busy wait */
171 FD_ZERO(&rfds); 175 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err;
172 FD_SET(sock, &rfds);
173 err = sock_select(0, &rfds, NULL, NULL, tm);
174 if (err == 0) return io_strerror(IO_TIMEOUT);
175 else if (err < 0) break;
176 } 176 }
177 return sock_strerror(); 177 /* can't reach here */
178 return IO_UNKNOWN;
178} 179}
179 180
180/*-------------------------------------------------------------------------*\ 181/*-------------------------------------------------------------------------*\
@@ -182,131 +183,93 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
182\*-------------------------------------------------------------------------*/ 183\*-------------------------------------------------------------------------*/
183int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm) 184int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
184{ 185{
185 t_sock sock = *ps; 186 int err;
186 /* avoid making system calls on closed sockets */ 187 /* avoid making system calls on closed sockets */
187 if (sock == SOCK_INVALID) return IO_CLOSED; 188 if (*ps == SOCK_INVALID) return IO_CLOSED;
189 /* loop until we send something or we give up on error */
190 *sent = 0;
188 for ( ;; ) { 191 for ( ;; ) {
189 fd_set fds;
190 int ret, put;
191 /* try to send something */ 192 /* try to send something */
192 put = send(sock, data, (int) count, 0); 193 int put = send(*ps, data, (int) count, 0);
193 /* if we sent something, we are done */ 194 /* if we sent something, we are done */
194 if (put > 0) { 195 if (put > 0) {
195 *sent = put; 196 *sent = put;
196 return IO_DONE; 197 return IO_DONE;
197 } 198 }
198 /* deal with failure */ 199 /* deal with failure */
199 *sent = 0; 200 err = WSAGetLastError();
200 ret = WSAGetLastError();
201 /* check for connection closed */
202 if (wisclosed(ret)) return IO_CLOSED;
203 /* we can only proceed if there was no serious error */ 201 /* we can only proceed if there was no serious error */
204 if (ret != WSAEWOULDBLOCK) return IO_USER; 202 if (err != WSAEWOULDBLOCK) return err;
205 /* optimize for the timeout = 0 case */ 203 /* avoid busy wait */
206 if (tm_get(tm) == 0.0) return IO_TIMEOUT; 204 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err;
207 /* run select to avoid busy wait */
208 FD_ZERO(&fds);
209 FD_SET(sock, &fds);
210 ret = sock_select(0, NULL, &fds, NULL, tm);
211 if (ret == 0) return IO_TIMEOUT;
212 else if (ret < 0) break;
213 } 205 }
214 return IO_USER; 206 /* can't reach here */
207 return IO_UNKNOWN;
215} 208}
216 209
217/*-------------------------------------------------------------------------*\ 210/*-------------------------------------------------------------------------*\
218* Sendto with timeout 211* Sendto with timeout
219\*-------------------------------------------------------------------------*/ 212\*-------------------------------------------------------------------------*/
220int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, 213int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
221 SA *addr, socklen_t addr_len, p_tm tm) 214 SA *addr, socklen_t len, p_tm tm)
222{ 215{
223 t_sock sock = *ps; 216 int err;
224 /* avoid making system calls on closed sockets */ 217 if (*ps == SOCK_INVALID) return IO_CLOSED;
225 if (sock == SOCK_INVALID) return IO_CLOSED; 218 *sent = 0;
226 for ( ;; ) { 219 for ( ;; ) {
227 fd_set fds; 220 int put = send(*ps, data, (int) count, 0);
228 int ret, put;
229 /* try to send something */
230 put = sendto(sock, data, (int) count, 0, addr, addr_len);
231 /* if we sent something, we are done */
232 if (put > 0) { 221 if (put > 0) {
233 *sent = put; 222 *sent = put;
234 return IO_DONE; 223 return IO_DONE;
235 } 224 }
236 /* deal with failure */ 225 err = WSAGetLastError();
237 *sent = 0; 226 if (err != WSAEWOULDBLOCK) return err;
238 ret = WSAGetLastError(); 227 if ((err = sock_waitfd(*ps, WAITFD_W, tm)) != IO_DONE) return err;
239 /* check for connection closed */
240 if (wisclosed(ret)) return IO_CLOSED;
241 /* we can only proceed if there was no serious error */
242 if (ret != WSAEWOULDBLOCK) return IO_USER;
243 /* optimize for the timeout = 0 case */
244 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
245 /* run select to avoid busy wait */
246 FD_ZERO(&fds);
247 FD_SET(sock, &fds);
248 ret = sock_select(0, NULL, &fds, NULL, tm);
249 if (ret == 0) return IO_TIMEOUT;
250 else if (ret < 0) break;
251 } 228 }
252 return IO_USER; 229 return IO_UNKNOWN;
253} 230}
254 231
255/*-------------------------------------------------------------------------*\ 232/*-------------------------------------------------------------------------*\
256* Receive with timeout 233* Receive with timeout
257\*-------------------------------------------------------------------------*/ 234\*-------------------------------------------------------------------------*/
258int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) 235int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) {
259{ 236 int err;
260 t_sock sock = *ps; 237 if (*ps == SOCK_INVALID) return IO_CLOSED;
261 if (sock == SOCK_INVALID) return IO_CLOSED; 238 *got = 0;
262 for ( ;; ) { 239 for ( ;; ) {
263 fd_set fds; 240 int taken = recv(*ps, data, (int) count, 0);
264 int ret, taken;
265 taken = recv(sock, data, (int) count, 0);
266 if (taken > 0) { 241 if (taken > 0) {
267 *got = taken; 242 *got = taken;
268 return IO_DONE; 243 return IO_DONE;
269 } 244 }
270 *got = 0; 245 if (taken == 0) return IO_CLOSED;
271 if (taken == 0 || wisclosed(ret = WSAGetLastError())) return IO_CLOSED; 246 err = WSAGetLastError();
272 if (ret != WSAEWOULDBLOCK) return IO_USER; 247 if (err != WSAEWOULDBLOCK) return err;
273 if (tm_get(tm) == 0.0) return IO_TIMEOUT; 248 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err;
274 FD_ZERO(&fds);
275 FD_SET(sock, &fds);
276 ret = sock_select(0, &fds, NULL, NULL, tm);
277 if (ret == 0) return IO_TIMEOUT;
278 else if (ret < 0) break;
279 } 249 }
280 return IO_TIMEOUT; 250 return IO_UNKNOWN;
281} 251}
282 252
283/*-------------------------------------------------------------------------*\ 253/*-------------------------------------------------------------------------*\
284* Recvfrom with timeout 254* Recvfrom with timeout
285\*-------------------------------------------------------------------------*/ 255\*-------------------------------------------------------------------------*/
286int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, 256int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
287 SA *addr, socklen_t *addr_len, p_tm tm) 257 SA *addr, socklen_t *len, p_tm tm) {
288{ 258 int err;
289 t_sock sock = *ps; 259 if (*ps == SOCK_INVALID) return IO_CLOSED;
290 if (sock == SOCK_INVALID) return IO_CLOSED; 260 *got = 0;
291 for ( ;; ) { 261 for ( ;; ) {
292 fd_set fds; 262 int taken = recvfrom(*ps, data, (int) count, 0, addr, len);
293 int ret, taken;
294 taken = recvfrom(sock, data, (int) count, 0, addr, addr_len);
295 if (taken > 0) { 263 if (taken > 0) {
296 *got = taken; 264 *got = taken;
297 return IO_DONE; 265 return IO_DONE;
298 } 266 }
299 *got = 0; 267 if (taken == 0) return IO_CLOSED;
300 if (taken == 0 || wisclosed(ret = WSAGetLastError())) return IO_CLOSED; 268 err = WSAGetLastError();
301 if (ret != WSAEWOULDBLOCK) return IO_USER; 269 if (err != WSAEWOULDBLOCK) return err;
302 if (tm_get(tm) == 0.0) return IO_TIMEOUT; 270 if ((err = sock_waitfd(*ps, WAITFD_R, tm)) != IO_DONE) return err;
303 FD_ZERO(&fds);
304 FD_SET(sock, &fds);
305 ret = sock_select(0, &fds, NULL, NULL, tm);
306 if (ret == 0) return IO_TIMEOUT;
307 else if (ret < 0) break;
308 } 271 }
309 return IO_TIMEOUT; 272 return IO_UNKNOWN;
310} 273}
311 274
312/*-------------------------------------------------------------------------*\ 275/*-------------------------------------------------------------------------*\
@@ -326,138 +289,96 @@ void sock_setnonblocking(p_sock ps) {
326} 289}
327 290
328/*-------------------------------------------------------------------------*\ 291/*-------------------------------------------------------------------------*\
292* DNS helpers
293\*-------------------------------------------------------------------------*/
294int sock_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
295 *hp = gethostbyaddr(addr, len, AF_INET);
296 if (*hp) return IO_DONE;
297 else return h_errno;
298}
299
300int sock_gethostbyname(const char *addr, struct hostent **hp) {
301 *hp = gethostbyname(addr);
302 if (*hp) return IO_DONE;
303 else return h_errno;
304}
305
306/*-------------------------------------------------------------------------*\
329* Error translation functions 307* Error translation functions
330\*-------------------------------------------------------------------------*/ 308\*-------------------------------------------------------------------------*/
331const char *sock_hoststrerror(void) { 309const char *sock_hoststrerror(int err) {
332 int err = WSAGetLastError(); 310 if (err <= 0) return io_strerror(err);
333 switch (err) { 311 switch (err) {
334 case WSAHOST_NOT_FOUND: 312 case WSAHOST_NOT_FOUND: return "host_not_found";
335 return "host not found"; 313 default: return wstrerror(err);
336 default:
337 return wstrerror(err);
338 } 314 }
339} 315}
340 316
341const char *sock_strerror(void) { 317const char *sock_strerror(int err) {
342 int err = WSAGetLastError(); 318 if (err <= 0) return io_strerror(err);
343 switch (err) { 319 switch (err) {
344 case WSAEADDRINUSE: 320 case WSAEADDRINUSE: return "eaddrinuse";
345 return "address already in use"; 321 case WSAECONNREFUSED: return "econnrefused";
346 default: 322 case WSAECONNABORTED: return "closed";
347 return wstrerror(err); 323 case WSAECONNRESET: return "closed";
324 case WSAETIMEDOUT: return "timeout";
325 default: return wstrerror(err);
348 } 326 }
349} 327}
350 328
351const char *sock_geterr(p_sock ps, int code) { 329const char *sock_ioerror(p_sock ps, int err) {
352 (void) ps; 330 (void) ps;
353 (void) code; 331 return sock_strerror(err);
354 return sock_strerror();
355}
356
357int wisclosed(int err) {
358 switch (err) {
359 case WSAECONNRESET:
360 case WSAECONNABORTED:
361 case WSAESHUTDOWN:
362 case WSAENOTCONN:
363 return 1;
364 default:
365 return 0;
366 }
367} 332}
368 333
369static const char *wstrerror(int err) { 334static const char *wstrerror(int err) {
370 switch (err) { 335 switch (err) {
371 case WSAEINTR: 336 case WSAEINTR: return "Interrupted function call";
372 return "WSAEINTR: Interrupted function call"; 337 case WSAEACCES: return "Permission denied";
373 case WSAEACCES: 338 case WSAEFAULT: return "Bad address";
374 return "WSAEACCES: Permission denied"; 339 case WSAEINVAL: return "Invalid argument";
375 case WSAEFAULT: 340 case WSAEMFILE: return "Too many open files";
376 return "WSAEFAULT: Bad address"; 341 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
377 case WSAEINVAL: 342 case WSAEINPROGRESS: return "Operation now in progress";
378 return "WSAEINVAL: Invalid argument"; 343 case WSAEALREADY: return "Operation already in progress";
379 case WSAEMFILE: 344 case WSAENOTSOCK: return "Socket operation on nonsocket";
380 return "WSAEMFILE: Too many open files"; 345 case WSAEDESTADDRREQ: return "Destination address required";
381 case WSAEWOULDBLOCK: 346 case WSAEMSGSIZE: return "Message too long";
382 return "WSAEWOULDBLOCK: Resource temporarily unavailable"; 347 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
383 case WSAEINPROGRESS: 348 case WSAENOPROTOOPT: return "Bad protocol option";
384 return "WSAEINPROGRESS: Operation now in progress"; 349 case WSAEPROTONOSUPPORT: return "Protocol not supported";
385 case WSAEALREADY: 350 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
386 return "WSAEALREADY: Operation already in progress"; 351 case WSAEOPNOTSUPP: return "Operation not supported";
387 case WSAENOTSOCK: 352 case WSAEPFNOSUPPORT: return "Protocol family not supported";
388 return "WSAENOTSOCK: Socket operation on nonsocket"; 353 case WSAEAFNOSUPPORT:
389 case WSAEDESTADDRREQ: 354 return "Address family not supported by protocol family";
390 return "WSAEDESTADDRREQ: Destination address required"; 355 case WSAEADDRINUSE: return "Address already in use";
391 case WSAEMSGSIZE: 356 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
392 return "WSAEMSGSIZE: Message too long"; 357 case WSAENETDOWN: return "Network is down";
393 case WSAEPROTOTYPE: 358 case WSAENETUNREACH: return "Network is unreachable";
394 return "WSAEPROTOTYPE: Protocol wrong type for socket"; 359 case WSAENETRESET: return "Network dropped connection on reset";
395 case WSAENOPROTOOPT: 360 case WSAECONNABORTED: return "Software caused connection abort";
396 return "WSAENOPROTOOPT: Bad protocol option"; 361 case WSAECONNRESET: return "Connection reset by peer";
397 case WSAEPROTONOSUPPORT: 362 case WSAENOBUFS: return "No buffer space available";
398 return "WSAEPROTONOSUPPORT: Protocol not supported"; 363 case WSAEISCONN: return "Socket is already connected";
399 case WSAESOCKTNOSUPPORT: 364 case WSAENOTCONN: return "Socket is not connected";
400 return "WSAESOCKTNOSUPPORT: Socket type not supported"; 365 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
401 case WSAEOPNOTSUPP: 366 case WSAETIMEDOUT: return "Connection timed out";
402 return "WSAEOPNOTSUPP: Operation not supported"; 367 case WSAECONNREFUSED: return "Connection refused";
403 case WSAEPFNOSUPPORT: 368 case WSAEHOSTDOWN: return "Host is down";
404 return "WSAEPFNOSUPPORT: Protocol family not supported"; 369 case WSAEHOSTUNREACH: return "No route to host";
405 case WSAEAFNOSUPPORT: 370 case WSAEPROCLIM: return "Too many processes";
406 return "WSAEAFNOSUPPORT: Address family not supported by " 371 case WSASYSNOTREADY: return "Network subsystem is unavailable";
407 "protocol family"; 372 case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
408 case WSAEADDRINUSE: 373 case WSANOTINITIALISED:
409 return "WSAEADDRINUSE: Address already in use"; 374 return "Successful WSAStartup not yet performed";
410 case WSAEADDRNOTAVAIL: 375 case WSAEDISCON: return "Graceful shutdown in progress";
411 return "WSAEADDRNOTAVAIL: Cannot assign requested address"; 376 case WSATYPE_NOT_FOUND: return "Class type not found";
412 case WSAENETDOWN: 377 case WSAHOST_NOT_FOUND: return "Host not found";
413 return "WSAENETDOWN: Network is down"; 378 case WSATRY_AGAIN: return "Nonauthoritative host not found";
414 case WSAENETUNREACH: 379 case WSANO_RECOVERY: return "Nonrecoverable name lookup error";
415 return "WSAENETUNREACH: Network is unreachable"; 380 case WSANO_DATA: return "Valid name, no data record of requested type";
416 case WSAENETRESET: 381 case WSASYSCALLFAILURE: return "System call failure";
417 return "WSAENETRESET: Network dropped connection on reset"; 382 default: return "Unknown error";
418 case WSAECONNABORTED:
419 return "WSAECONNABORTED: Software caused connection abort";
420 case WSAECONNRESET:
421 return "WSAECONNRESET: Connection reset by peer";
422 case WSAENOBUFS:
423 return "WSAENOBUFS: No buffer space available";
424 case WSAEISCONN:
425 return "WSAEISCONN: Socket is already connected";
426 case WSAENOTCONN:
427 return "WSAENOTCONN: Socket is not connected";
428 case WSAESHUTDOWN:
429 return "WSAESHUTDOWN: Cannot send after socket shutdown";
430 case WSAETIMEDOUT:
431 return "WSAETIMEDOUT: Connection timed out";
432 case WSAECONNREFUSED:
433 return "WSAECONNREFUSED: Connection refused";
434 case WSAEHOSTDOWN:
435 return "WSAEHOSTDOWN: Host is down";
436 case WSAEHOSTUNREACH:
437 return "WSAEHOSTUNREACH: No route to host";
438 case WSAEPROCLIM:
439 return "WSAEPROCLIM: Too many processes";
440 case WSASYSNOTREADY:
441 return "WSASYSNOTREADY: Network subsystem is unavailable";
442 case WSAVERNOTSUPPORTED:
443 return "WSAVERNOTSUPPORTED: Winsock.dll version out of range";
444 case WSANOTINITIALISED:
445 return "WSANOTINITIALISED: Successful WSAStartup not yet performed";
446 case WSAEDISCON:
447 return "WSAEDISCON: Graceful shutdown in progress";
448 case WSATYPE_NOT_FOUND:
449 return "WSATYPE_NOT_FOUND: Class type not found";
450 case WSAHOST_NOT_FOUND:
451 return "WSAHOST_NOT_FOUND: Host not found";
452 case WSATRY_AGAIN:
453 return "WSATRY_AGAIN: Nonauthoritative host not found";
454 case WSANO_RECOVERY:
455 return "WSANO_RECOVERY: Nonrecoverable name lookup error";
456 case WSANO_DATA:
457 return "WSANO_DATA: Valid name, no data record of requested type";
458 case WSASYSCALLFAILURE:
459 return "WSASYSCALLFAILURE: System call failure";
460 default:
461 return "Unknown error";
462 } 383 }
463} 384}
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()
283 if not data then 283 if not data then
284 pass("ok") 284 pass("ok")
285 data = socket.connect(host, port) 285 data = socket.connect(host, port)
286 else fail("should not have connected!") end 286 else
287 pass("gethostbyname returns localhost on empty string...")
288 end
287end 289end
288 290
289------------------------------------------------------------------------ 291------------------------------------------------------------------------
@@ -374,19 +376,17 @@ end
374 376
375------------------------------------------------------------------------ 377------------------------------------------------------------------------
376function connect_timeout() 378function connect_timeout()
377 io.stderr:write("connect with timeout (if it hangs, it failed): ") 379 io.stderr:write("connect with timeout (if it hangs, it failed!): ")
378 local t = socket.gettime() 380 local t = socket.gettime()
379 local c, e = socket.tcp() 381 local c, e = socket.tcp()
380 assert(c, e) 382 assert(c, e)
381 c:settimeout(0.1) 383 c:settimeout(0.1)
382 ip = socket.dns.toip("ibere.tecgraf.puc-rio.br")
383 if not ip then return end
384 local t = socket.gettime() 384 local t = socket.gettime()
385 local r, e = c:connect(ip, 80) 385 local r, e = c:connect("127.0.0.2", 80)
386 assert(not r, "should not connect") 386 assert(not r, "should not connect")
387 --assert(e == "timeout", e)
388 assert(socket.gettime() - t < 2, "took too long to give up.") 387 assert(socket.gettime() - t < 2, "took too long to give up.")
389 c:close() 388 c:close()
389 print("ok")
390end 390end
391 391
392------------------------------------------------------------------------ 392------------------------------------------------------------------------