aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-24 00:18:19 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-24 00:18:19 +0000
commit0c9f420a3549df3fb331bb24157b65a3301641d4 (patch)
treee1b6ce40b55a77ed2bc20493f10f8239b7c00071
parent42e0e74487ca62b58a8a1fa06580154c632b4942 (diff)
downloadluasocket-0c9f420a3549df3fb331bb24157b65a3301641d4.tar.gz
luasocket-0c9f420a3549df3fb331bb24157b65a3301641d4.tar.bz2
luasocket-0c9f420a3549df3fb331bb24157b65a3301641d4.zip
New accept/connect code.
Better error checking. Better tests. __tostring implemented.
-rw-r--r--TODO3
-rw-r--r--src/auxiliar.c30
-rw-r--r--src/inet.c14
-rw-r--r--src/inet.h2
-rw-r--r--src/socket.h10
-rw-r--r--src/tcp.c54
-rw-r--r--src/udp.c18
-rw-r--r--src/usocket.c181
-rw-r--r--src/wsocket.c215
-rw-r--r--test/testclnt.lua89
10 files changed, 422 insertions, 194 deletions
diff --git a/TODO b/TODO
index 835929f..f6a67f1 100644
--- a/TODO
+++ b/TODO
@@ -12,6 +12,9 @@ manual
12 local connect 12 local connect
13 add thanks to 'carlos cassino' and 'david burgess' 13 add thanks to 'carlos cassino' and 'david burgess'
14 add new ip- options and reuseaddr option 14 add new ip- options and reuseaddr option
15 add listen to manual
16 bind method doesn't do listen anymore
17 bind doesn't turn an object into a server object: listen does.
15 18
16tests 19tests
17 checar todos os metodos 20 checar todos os metodos
diff --git a/src/auxiliar.c b/src/auxiliar.c
index 6888f9c..9a249b6 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -5,6 +5,7 @@
5* RCS ID: $Id$ 5* RCS ID: $Id$
6\*=========================================================================*/ 6\*=========================================================================*/
7#include <string.h> 7#include <string.h>
8#include <stdio.h>
8 9
9#include "luasocket.h" 10#include "luasocket.h"
10#include "auxiliar.h" 11#include "auxiliar.h"
@@ -13,6 +14,27 @@
13* Exported functions 14* Exported functions
14\*=========================================================================*/ 15\*=========================================================================*/
15/*-------------------------------------------------------------------------*\ 16/*-------------------------------------------------------------------------*\
17* Prints the value of a class in a nice way
18\*-------------------------------------------------------------------------*/
19int aux_meth_tostring(lua_State *L)
20{
21 char buf[32];
22 if (!lua_getmetatable(L, 1)) goto error;
23 lua_pushstring(L, "__index");
24 lua_gettable(L, -2);
25 if (!lua_istable(L, -1)) goto error;
26 lua_pushstring(L, "class");
27 lua_gettable(L, -2);
28 if (!lua_isstring(L, -1)) goto error;
29 sprintf(buf, "%p", lua_touserdata(L, 1));
30 lua_pushfstring(L, "socket: %s: %s", lua_tostring(L, -1), buf);
31 return 1;
32error:
33 lua_pushnil(L);
34 return 1;
35}
36
37/*-------------------------------------------------------------------------*\
16* Initializes the module 38* Initializes the module
17\*-------------------------------------------------------------------------*/ 39\*-------------------------------------------------------------------------*/
18void aux_open(lua_State *L) 40void aux_open(lua_State *L)
@@ -26,14 +48,18 @@ void aux_open(lua_State *L)
26void aux_newclass(lua_State *L, const char *classname, luaL_reg *func) 48void aux_newclass(lua_State *L, const char *classname, luaL_reg *func)
27{ 49{
28 luaL_newmetatable(L, classname); /* mt */ 50 luaL_newmetatable(L, classname); /* mt */
51 /* set __tostring metamethod */
52 lua_pushstring(L, "__tostring");
53 lua_pushcfunction(L, aux_meth_tostring);
54 lua_rawset(L, -3);
55 /* create __index table to place methods */
29 lua_pushstring(L, "__index"); /* mt,"__index" */ 56 lua_pushstring(L, "__index"); /* mt,"__index" */
30 lua_newtable(L); /* mt,"__index",it */ 57 lua_newtable(L); /* mt,"__index",it */
31 luaL_openlib(L, NULL, func, 0); 58 luaL_openlib(L, NULL, func, 0);
32#ifdef LUASOCKET_DEBUG 59 /* put class name into class metatable */
33 lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ 60 lua_pushstring(L, "class"); /* mt,"__index",it,"class" */
34 lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ 61 lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */
35 lua_rawset(L, -3); /* mt,"__index",it */ 62 lua_rawset(L, -3); /* mt,"__index",it */
36#endif
37 /* get __gc method from class and use it for garbage collection */ 63 /* get __gc method from class and use it for garbage collection */
38 lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc" */ 64 lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc" */
39 lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc","__gc" */ 65 lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc","__gc" */
diff --git a/src/inet.c b/src/inet.c
index f6c2a6f..dff4bf2 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -213,8 +213,7 @@ const char *inet_tryconnect(p_sock ps, const char *address,
213/*-------------------------------------------------------------------------*\ 213/*-------------------------------------------------------------------------*\
214* Tries to bind socket to (address, port) 214* Tries to bind socket to (address, port)
215\*-------------------------------------------------------------------------*/ 215\*-------------------------------------------------------------------------*/
216const char *inet_trybind(p_sock ps, const char *address, unsigned short port, 216const char *inet_trybind(p_sock ps, const char *address, unsigned short port)
217 int backlog)
218{ 217{
219 struct sockaddr_in local; 218 struct sockaddr_in local;
220 const char *err; 219 const char *err;
@@ -231,16 +230,9 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
231 addr = (struct in_addr **) hp->h_addr_list; 230 addr = (struct in_addr **) hp->h_addr_list;
232 memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); 231 memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
233 } 232 }
234 sock_setblocking(ps);
235 err = sock_bind(ps, (SA *) &local, sizeof(local)); 233 err = sock_bind(ps, (SA *) &local, sizeof(local));
236 if (err) { 234 if (err) sock_destroy(ps);
237 sock_destroy(ps); 235 return err;
238 return err;
239 } else {
240 sock_setnonblocking(ps);
241 if (backlog >= 0) sock_listen(ps, backlog);
242 return NULL;
243 }
244} 236}
245 237
246/*-------------------------------------------------------------------------*\ 238/*-------------------------------------------------------------------------*\
diff --git a/src/inet.h b/src/inet.h
index 28cf823..87da23a 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -30,7 +30,7 @@ const char *inet_trycreate(p_sock ps, int type);
30const char *inet_tryconnect(p_sock ps, const char *address, 30const char *inet_tryconnect(p_sock ps, const char *address,
31 unsigned short port, p_tm tm); 31 unsigned short port, p_tm tm);
32const char *inet_trybind(p_sock ps, const char *address, 32const char *inet_trybind(p_sock ps, const char *address,
33 unsigned short port, int backlog); 33 unsigned short port);
34 34
35int inet_meth_getpeername(lua_State *L, p_sock ps); 35int inet_meth_getpeername(lua_State *L, p_sock ps);
36int inet_meth_getsockname(lua_State *L, p_sock ps); 36int inet_meth_getsockname(lua_State *L, p_sock ps);
diff --git a/src/socket.h b/src/socket.h
index 7c84baa..2e7b6f9 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -39,7 +39,6 @@ typedef struct sockaddr SA;
39\*=========================================================================*/ 39\*=========================================================================*/
40int sock_open(void); 40int sock_open(void);
41void sock_destroy(p_sock ps); 41void sock_destroy(p_sock ps);
42void sock_listen(p_sock ps, int backlog);
43void sock_shutdown(p_sock ps, int how); 42void sock_shutdown(p_sock ps, int how);
44int sock_send(p_sock ps, const char *data, size_t count, 43int sock_send(p_sock ps, const char *data, size_t count,
45 size_t *sent, int timeout); 44 size_t *sent, int timeout);
@@ -51,10 +50,15 @@ int sock_recvfrom(p_sock ps, char *data, size_t count,
51 size_t *got, SA *addr, socklen_t *addr_len, int timeout); 50 size_t *got, SA *addr, socklen_t *addr_len, int timeout);
52void sock_setnonblocking(p_sock ps); 51void sock_setnonblocking(p_sock ps);
53void sock_setblocking(p_sock ps); 52void sock_setblocking(p_sock ps);
54int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, p_tm tm); 53int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout);
54
55const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm); 55const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm);
56const char *sock_create(p_sock ps, int domain, int type, int protocol); 56const char *sock_create(p_sock ps, int domain, int type, int protocol);
57const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len); 57const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
58const char *sock_hoststrerror(void); 58const char *sock_listen(p_sock ps, int backlog);
59const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
60 socklen_t *addr_len, p_tm tm);
61
62const char *sock_hoststrerror();
59 63
60#endif /* SOCK_H */ 64#endif /* SOCK_H */
diff --git a/src/tcp.c b/src/tcp.c
index 01b07ee..4b3b0cc 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -22,6 +22,7 @@
22\*=========================================================================*/ 22\*=========================================================================*/
23static int global_create(lua_State *L); 23static int global_create(lua_State *L);
24static int meth_connect(lua_State *L); 24static int meth_connect(lua_State *L);
25static int meth_listen(lua_State *L);
25static int meth_bind(lua_State *L); 26static int meth_bind(lua_State *L);
26static int meth_send(lua_State *L); 27static int meth_send(lua_State *L);
27static int meth_getsockname(lua_State *L); 28static int meth_getsockname(lua_State *L);
@@ -32,7 +33,8 @@ static int meth_accept(lua_State *L);
32static int meth_close(lua_State *L); 33static int meth_close(lua_State *L);
33static int meth_setoption(lua_State *L); 34static int meth_setoption(lua_State *L);
34static int meth_settimeout(lua_State *L); 35static int meth_settimeout(lua_State *L);
35static int meth_fd(lua_State *L); 36static int meth_getfd(lua_State *L);
37static int meth_setfd(lua_State *L);
36static int meth_dirty(lua_State *L); 38static int meth_dirty(lua_State *L);
37 39
38/* tcp object methods */ 40/* tcp object methods */
@@ -41,6 +43,7 @@ static luaL_reg tcp[] = {
41 {"send", meth_send}, 43 {"send", meth_send},
42 {"receive", meth_receive}, 44 {"receive", meth_receive},
43 {"bind", meth_bind}, 45 {"bind", meth_bind},
46 {"listen", meth_listen},
44 {"accept", meth_accept}, 47 {"accept", meth_accept},
45 {"setpeername", meth_connect}, 48 {"setpeername", meth_connect},
46 {"setsockname", meth_bind}, 49 {"setsockname", meth_bind},
@@ -51,7 +54,8 @@ static luaL_reg tcp[] = {
51 {"shutdown", meth_shutdown}, 54 {"shutdown", meth_shutdown},
52 {"setoption", meth_setoption}, 55 {"setoption", meth_setoption},
53 {"__gc", meth_close}, 56 {"__gc", meth_close},
54 {"fd", meth_fd}, 57 {"getfd", meth_getfd},
58 {"setfd", meth_setfd},
55 {"dirty", meth_dirty}, 59 {"dirty", meth_dirty},
56 {NULL, NULL} 60 {NULL, NULL}
57}; 61};
@@ -124,16 +128,24 @@ static int meth_setoption(lua_State *L)
124/*-------------------------------------------------------------------------*\ 128/*-------------------------------------------------------------------------*\
125* Select support methods 129* Select support methods
126\*-------------------------------------------------------------------------*/ 130\*-------------------------------------------------------------------------*/
127static int meth_fd(lua_State *L) 131static int meth_getfd(lua_State *L)
128{ 132{
129 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); 133 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
130 lua_pushnumber(L, tcp->sock); 134 lua_pushnumber(L, tcp->sock);
131 return 1; 135 return 1;
132} 136}
133 137
138/* this is very dangerous, but can be handy for those that are brave enough */
139static int meth_setfd(lua_State *L)
140{
141 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
142 tcp->sock = (t_sock) luaL_checknumber(L, 2);
143 return 0;
144}
145
134static int meth_dirty(lua_State *L) 146static int meth_dirty(lua_State *L)
135{ 147{
136 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); 148 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
137 lua_pushboolean(L, !buf_isempty(&tcp->buf)); 149 lua_pushboolean(L, !buf_isempty(&tcp->buf));
138 return 1; 150 return 1;
139} 151}
@@ -147,9 +159,9 @@ static int meth_accept(lua_State *L)
147 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); 159 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
148 p_tm tm = tm_markstart(&server->tm); 160 p_tm tm = tm_markstart(&server->tm);
149 t_sock sock; 161 t_sock sock;
150 int err = sock_accept(&server->sock, &sock, NULL, NULL, tm); 162 const char *err = sock_accept(&server->sock, &sock, NULL, NULL, tm);
151 /* if successful, push client socket */ 163 /* if successful, push client socket */
152 if (err == IO_DONE) { 164 if (!err) {
153 p_tcp clnt = lua_newuserdata(L, sizeof(t_tcp)); 165 p_tcp clnt = lua_newuserdata(L, sizeof(t_tcp));
154 aux_setclass(L, "tcp{client}", -1); 166 aux_setclass(L, "tcp{client}", -1);
155 /* initialize structure fields */ 167 /* initialize structure fields */
@@ -160,28 +172,25 @@ static int meth_accept(lua_State *L)
160 return 1; 172 return 1;
161 } else { 173 } else {
162 lua_pushnil(L); 174 lua_pushnil(L);
163 io_pusherror(L, err); 175 lua_pushstring(L, err);
164 return 2; 176 return 2;
165 } 177 }
166} 178}
167 179
168/*-------------------------------------------------------------------------*\ 180/*-------------------------------------------------------------------------*\
169* Turns a master object into a server object 181* Binds an object to an address
170\*-------------------------------------------------------------------------*/ 182\*-------------------------------------------------------------------------*/
171static int meth_bind(lua_State *L) 183static int meth_bind(lua_State *L)
172{ 184{
173 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 185 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
174 const char *address = luaL_checkstring(L, 2); 186 const char *address = luaL_checkstring(L, 2);
175 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 187 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
176 int backlog = (int) luaL_optnumber(L, 4, 1); 188 const char *err = inet_trybind(&tcp->sock, address, port);
177 const char *err = inet_trybind(&tcp->sock, address, port, backlog);
178 if (err) { 189 if (err) {
179 lua_pushnil(L); 190 lua_pushnil(L);
180 lua_pushstring(L, err); 191 lua_pushstring(L, err);
181 return 2; 192 return 2;
182 } 193 }
183 /* turn master object into a server object if there was a listen */
184 if (backlog >= 0) aux_setclass(L, "tcp{server}", 1);
185 lua_pushnumber(L, 1); 194 lua_pushnumber(L, 1);
186 return 1; 195 return 1;
187} 196}
@@ -218,6 +227,25 @@ static int meth_close(lua_State *L)
218} 227}
219 228
220/*-------------------------------------------------------------------------*\ 229/*-------------------------------------------------------------------------*\
230* Puts the sockt in listen mode
231\*-------------------------------------------------------------------------*/
232static int meth_listen(lua_State *L)
233{
234 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
235 int backlog = (int) luaL_checknumber(L, 2);
236 const char *err = sock_listen(&tcp->sock, backlog);
237 if (err) {
238 lua_pushnil(L);
239 lua_pushstring(L, err);
240 return 2;
241 }
242 /* turn master object into a server object */
243 aux_setclass(L, "tcp{server}", 1);
244 lua_pushnumber(L, 1);
245 return 1;
246}
247
248/*-------------------------------------------------------------------------*\
221* Shuts the connection down partially 249* Shuts the connection down partially
222\*-------------------------------------------------------------------------*/ 250\*-------------------------------------------------------------------------*/
223static int meth_shutdown(lua_State *L) 251static int meth_shutdown(lua_State *L)
diff --git a/src/udp.c b/src/udp.c
index 115e749..14029f9 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -33,7 +33,8 @@ static int meth_close(lua_State *L);
33static int meth_shutdown(lua_State *L); 33static int meth_shutdown(lua_State *L);
34static int meth_setoption(lua_State *L); 34static int meth_setoption(lua_State *L);
35static int meth_settimeout(lua_State *L); 35static int meth_settimeout(lua_State *L);
36static int meth_fd(lua_State *L); 36static int meth_getfd(lua_State *L);
37static int meth_setfd(lua_State *L);
37static int meth_dirty(lua_State *L); 38static int meth_dirty(lua_State *L);
38 39
39/* udp object methods */ 40/* udp object methods */
@@ -51,7 +52,8 @@ static luaL_reg udp[] = {
51 {"shutdown", meth_shutdown}, 52 {"shutdown", meth_shutdown},
52 {"setoption", meth_setoption}, 53 {"setoption", meth_setoption},
53 {"__gc", meth_close}, 54 {"__gc", meth_close},
54 {"fd", meth_fd}, 55 {"getfd", meth_getfd},
56 {"setfd", meth_setfd},
55 {"dirty", meth_dirty}, 57 {"dirty", meth_dirty},
56 {NULL, NULL} 58 {NULL, NULL}
57}; 59};
@@ -194,13 +196,21 @@ static int meth_receivefrom(lua_State *L)
194/*-------------------------------------------------------------------------*\ 196/*-------------------------------------------------------------------------*\
195* Select support methods 197* Select support methods
196\*-------------------------------------------------------------------------*/ 198\*-------------------------------------------------------------------------*/
197static int meth_fd(lua_State *L) 199static int meth_getfd(lua_State *L)
198{ 200{
199 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 201 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
200 lua_pushnumber(L, udp->sock); 202 lua_pushnumber(L, udp->sock);
201 return 1; 203 return 1;
202} 204}
203 205
206/* this is very dangerous, but can be handy for those that are brave enough */
207static int meth_setfd(lua_State *L)
208{
209 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
210 udp->sock = (t_sock) luaL_checknumber(L, 2);
211 return 0;
212}
213
204static int meth_dirty(lua_State *L) 214static int meth_dirty(lua_State *L)
205{ 215{
206 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 216 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
@@ -312,7 +322,7 @@ static int meth_setsockname(lua_State *L)
312 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 322 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
313 const char *address = luaL_checkstring(L, 2); 323 const char *address = luaL_checkstring(L, 2);
314 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 324 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
315 const char *err = inet_trybind(&udp->sock, address, port, -1); 325 const char *err = inet_trybind(&udp->sock, address, port);
316 if (err) { 326 if (err) {
317 lua_pushnil(L); 327 lua_pushnil(L);
318 lua_pushstring(L, err); 328 lua_pushstring(L, err);
diff --git a/src/usocket.c b/src/usocket.c
index 5afa1bf..bece354 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -20,9 +20,11 @@
20 20
21#include "socket.h" 21#include "socket.h"
22 22
23static const char *sock_createstrerror(void); 23static const char *sock_createstrerror(int err);
24static const char *sock_bindstrerror(void); 24static const char *sock_bindstrerror(int err);
25static const char *sock_connectstrerror(void); 25static const char *sock_connectstrerror(int err);
26static const char *sock_acceptstrerror(int err);
27static const char *sock_listenstrerror(int err);
26 28
27/*-------------------------------------------------------------------------*\ 29/*-------------------------------------------------------------------------*\
28* Initializes module 30* Initializes module
@@ -46,19 +48,31 @@ int sock_open(void)
46void sock_destroy(p_sock ps) 48void sock_destroy(p_sock ps)
47{ 49{
48 if (*ps != SOCK_INVALID) { 50 if (*ps != SOCK_INVALID) {
51 sock_setblocking(ps);
49 close(*ps); 52 close(*ps);
50 *ps = SOCK_INVALID; 53 *ps = SOCK_INVALID;
51 } 54 }
52} 55}
53 56
54/*-------------------------------------------------------------------------*\ 57/*-------------------------------------------------------------------------*\
58* Select with int timeout in ms
59\*-------------------------------------------------------------------------*/
60int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout)
61{
62 struct timeval tv;
63 tv.tv_sec = timeout / 1000;
64 tv.tv_usec = (timeout % 1000) * 1000;
65 return select(n, rfds, wfds, efds, timeout >= 0? &tv: NULL);
66}
67
68/*-------------------------------------------------------------------------*\
55* Creates and sets up a socket 69* Creates and sets up a socket
56\*-------------------------------------------------------------------------*/ 70\*-------------------------------------------------------------------------*/
57const char *sock_create(p_sock ps, int domain, int type, int protocol) 71const char *sock_create(p_sock ps, int domain, int type, int protocol)
58{ 72{
59 int val = 1; 73 int val = 1;
60 t_sock sock = socket(domain, type, protocol); 74 t_sock sock = socket(domain, type, protocol);
61 if (sock == SOCK_INVALID) return sock_createstrerror(); 75 if (sock == SOCK_INVALID) return sock_createstrerror(errno);
62 *ps = sock; 76 *ps = sock;
63 sock_setnonblocking(ps); 77 sock_setnonblocking(ps);
64 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); 78 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
@@ -79,27 +93,22 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
79 /* if no error, we're done */ 93 /* if no error, we're done */
80 if (err == 0) return NULL; 94 if (err == 0) return NULL;
81 /* make sure the system is trying to connect */ 95 /* make sure the system is trying to connect */
82 if (errno != EINPROGRESS) return io_strerror(IO_ERROR); 96 if (errno != EINPROGRESS) return sock_connectstrerror(errno);
83 /* wait for a timeout or for the system's answer */ 97 /* wait for a timeout or for the system's answer */
84 for ( ;; ) { 98 for ( ;; ) {
85 struct timeval tv;
86 fd_set rfds, wfds, efds; 99 fd_set rfds, wfds, efds;
87 int timeout = tm_getretry(tm);
88 tv.tv_sec = timeout / 1000;
89 tv.tv_usec = (timeout % 1000) * 1000;
90 FD_ZERO(&rfds); FD_SET(sock, &rfds); 100 FD_ZERO(&rfds); FD_SET(sock, &rfds);
91 FD_ZERO(&wfds); FD_SET(sock, &wfds); 101 FD_ZERO(&wfds); FD_SET(sock, &wfds);
92 FD_ZERO(&efds); FD_SET(sock, &efds); 102 FD_ZERO(&efds); FD_SET(sock, &efds);
93 /* we run select to avoid busy waiting */ 103 /* we run select to avoid busy waiting */
94 err = select(sock+1, &rfds, &wfds, &efds, timeout >= 0? &tv: NULL); 104 do err = sock_select(sock+1, &rfds, &wfds, &efds, tm_getretry(tm));
95 /* if select was interrupted, try again */ 105 while (err < 0 && errno == EINTR);
96 if (err < 0 && errno == EINTR) continue;
97 /* if selects readable, try reading */ 106 /* if selects readable, try reading */
98 if (err > 0) { 107 if (err > 0) {
99 char dummy; 108 char dummy;
100 /* recv will set errno to the value a blocking connect would set */ 109 /* recv will set errno to the value a blocking connect would set */
101 if (recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN) 110 if (recv(sock, &dummy, 0, 0) < 0 && errno != EWOULDBLOCK)
102 return sock_connectstrerror(); 111 return sock_connectstrerror(errno);
103 else 112 else
104 return NULL; 113 return NULL;
105 /* if no event happened, there was a timeout */ 114 /* if no event happened, there was a timeout */
@@ -113,16 +122,24 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
113\*-------------------------------------------------------------------------*/ 122\*-------------------------------------------------------------------------*/
114const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) 123const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
115{ 124{
116 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); 125 const char *err = NULL;
117 else return NULL; 126 sock_setblocking(ps);
127 if (bind(*ps, addr, addr_len) < 0) err = sock_bindstrerror(errno);
128 sock_setnonblocking(ps);
129 return err;
118} 130}
119 131
120/*-------------------------------------------------------------------------*\ 132/*-------------------------------------------------------------------------*\
121* 133*
122\*-------------------------------------------------------------------------*/ 134\*-------------------------------------------------------------------------*/
123void sock_listen(p_sock ps, int backlog) 135const char* sock_listen(p_sock ps, int backlog)
124{ 136{
125 listen(*ps, backlog); 137 const char *err = NULL;
138 sock_setblocking(ps);
139 if (listen(*ps, backlog))
140 err = sock_listenstrerror(errno);
141 sock_setnonblocking(ps);
142 return err;
126} 143}
127 144
128/*-------------------------------------------------------------------------*\ 145/*-------------------------------------------------------------------------*\
@@ -130,35 +147,40 @@ void sock_listen(p_sock ps, int backlog)
130\*-------------------------------------------------------------------------*/ 147\*-------------------------------------------------------------------------*/
131void sock_shutdown(p_sock ps, int how) 148void sock_shutdown(p_sock ps, int how)
132{ 149{
150 sock_setblocking(ps);
133 shutdown(*ps, how); 151 shutdown(*ps, how);
152 sock_setnonblocking(ps);
134} 153}
135 154
136/*-------------------------------------------------------------------------*\ 155/*-------------------------------------------------------------------------*\
137* Accept with timeout 156* Accept with timeout
138\*-------------------------------------------------------------------------*/ 157\*-------------------------------------------------------------------------*/
139int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, p_tm tm) 158const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
159 socklen_t *addr_len, p_tm tm)
140{ 160{
141 t_sock sock = *ps; 161 t_sock sock = *ps;
142 SA dummy_addr; 162 SA dummy_addr;
143 socklen_t dummy_len = sizeof(dummy_addr); 163 socklen_t dummy_len = sizeof(dummy_addr);
144 if (sock == SOCK_INVALID) return IO_CLOSED; 164 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED);
145 if (!addr) addr = &dummy_addr; 165 if (!addr) addr = &dummy_addr;
146 if (!addr_len) addr_len = &dummy_len; 166 if (!addr_len) addr_len = &dummy_len;
147 for (;;) { 167 for (;;) {
148 int timeout = tm_getretry(tm); 168 int err;
149 struct timeval tv;
150 fd_set fds; 169 fd_set fds;
151 *pa = accept(sock, addr, addr_len); 170 *pa = accept(sock, addr, addr_len);
152 if (*pa != SOCK_INVALID) return IO_DONE; 171 /* if result is valid, we are done */
153 if (timeout == 0) return IO_TIMEOUT; 172 if (*pa != SOCK_INVALID) return NULL;
154 tv.tv_sec = timeout / 1000; 173 /* find out if we failed for a fatal reason */
155 tv.tv_usec = (timeout % 1000) * 1000; 174 if (errno != EWOULDBLOCK && errno != ECONNABORTED)
175 return sock_acceptstrerror(errno);
176 /* call select just to avoid busy-wait. */
156 FD_ZERO(&fds); 177 FD_ZERO(&fds);
157 FD_SET(sock, &fds); 178 FD_SET(sock, &fds);
158 /* call select just to avoid busy-wait. */ 179 do err = sock_select(sock+1, &fds, NULL, NULL, tm_getretry(tm));
159 select(sock+1, &fds, NULL, NULL, timeout >= 0? &tv: NULL); 180 while (err < 0 && errno == EINTR);
181 if (err == 0) return io_strerror(IO_TIMEOUT);
160 } 182 }
161 return IO_TIMEOUT; /* can't get here */ 183 return io_strerror(IO_TIMEOUT); /* can't get here */
162} 184}
163 185
164/*-------------------------------------------------------------------------*\ 186/*-------------------------------------------------------------------------*\
@@ -176,18 +198,15 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
176 while (put < 0 && errno == EINTR); 198 while (put < 0 && errno == EINTR);
177 /* deal with failure */ 199 /* deal with failure */
178 if (put <= 0) { 200 if (put <= 0) {
179 struct timeval tv;
180 fd_set fds; 201 fd_set fds;
181 /* in any case, nothing has been sent */ 202 /* in any case, nothing has been sent */
182 *sent = 0; 203 *sent = 0;
183 /* here we know the connection has been closed */ 204 /* here we know the connection has been closed */
184 if (errno == EPIPE) return IO_CLOSED; 205 if (errno == EPIPE) return IO_CLOSED;
185 /* run select to avoid busy wait */ 206 /* run select to avoid busy wait */
186 tv.tv_sec = timeout / 1000;
187 tv.tv_usec = (timeout % 1000) * 1000;
188 FD_ZERO(&fds); 207 FD_ZERO(&fds);
189 FD_SET(sock, &fds); 208 FD_SET(sock, &fds);
190 if (select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL) <= 0) { 209 if (sock_select(sock+1, NULL, &fds, NULL, timeout) <= 0) {
191 /* here the call was interrupted. calling again might work */ 210 /* here the call was interrupted. calling again might work */
192 if (errno == EINTR) return IO_RETRY; 211 if (errno == EINTR) return IO_RETRY;
193 /* here there was no data before timeout */ 212 /* here there was no data before timeout */
@@ -213,15 +232,12 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
213 do put = sendto(sock, data, count, 0, addr, addr_len); 232 do put = sendto(sock, data, count, 0, addr, addr_len);
214 while (put < 0 && errno == EINTR); 233 while (put < 0 && errno == EINTR);
215 if (put <= 0) { 234 if (put <= 0) {
216 struct timeval tv;
217 fd_set fds; 235 fd_set fds;
218 *sent = 0; 236 *sent = 0;
219 if (errno == EPIPE) return IO_CLOSED; 237 if (errno == EPIPE) return IO_CLOSED;
220 tv.tv_sec = timeout / 1000;
221 tv.tv_usec = (timeout % 1000) * 1000;
222 FD_ZERO(&fds); 238 FD_ZERO(&fds);
223 FD_SET(sock, &fds); 239 FD_SET(sock, &fds);
224 if (select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL) <= 0) { 240 if (sock_select(sock+1, NULL, &fds, NULL, timeout) <= 0) {
225 if (errno == EINTR) return IO_RETRY; 241 if (errno == EINTR) return IO_RETRY;
226 else return IO_TIMEOUT; 242 else return IO_TIMEOUT;
227 } else return IO_DONE; 243 } else return IO_DONE;
@@ -242,16 +258,13 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
242 do taken = read(sock, data, count); 258 do taken = read(sock, data, count);
243 while (taken < 0 && errno == EINTR); 259 while (taken < 0 && errno == EINTR);
244 if (taken <= 0) { 260 if (taken <= 0) {
245 struct timeval tv;
246 fd_set fds; 261 fd_set fds;
247 int ret; 262 int ret;
248 *got = 0; 263 *got = 0;
249 if (taken == 0) return IO_CLOSED; 264 if (taken == 0) return IO_CLOSED;
250 tv.tv_sec = timeout / 1000;
251 tv.tv_usec = (timeout % 1000) * 1000;
252 FD_ZERO(&fds); 265 FD_ZERO(&fds);
253 FD_SET(sock, &fds); 266 FD_SET(sock, &fds);
254 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 267 ret = sock_select(sock+1, &fds, NULL, NULL, timeout);
255 if (ret < 0 && errno == EINTR) return IO_RETRY; 268 if (ret < 0 && errno == EINTR) return IO_RETRY;
256 if (ret == 0) return IO_TIMEOUT; 269 if (ret == 0) return IO_TIMEOUT;
257 else return IO_DONE; 270 else return IO_DONE;
@@ -273,16 +286,13 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
273 do taken = recvfrom(sock, data, count, 0, addr, addr_len); 286 do taken = recvfrom(sock, data, count, 0, addr, addr_len);
274 while (taken < 0 && errno == EINTR); 287 while (taken < 0 && errno == EINTR);
275 if (taken <= 0) { 288 if (taken <= 0) {
276 struct timeval tv;
277 fd_set fds; 289 fd_set fds;
278 int ret; 290 int ret;
279 *got = 0; 291 *got = 0;
280 if (taken == 0) return IO_CLOSED; 292 if (taken == 0) return IO_CLOSED;
281 tv.tv_sec = timeout / 1000;
282 tv.tv_usec = (timeout % 1000) * 1000;
283 FD_ZERO(&fds); 293 FD_ZERO(&fds);
284 FD_SET(sock, &fds); 294 FD_SET(sock, &fds);
285 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 295 ret = sock_select(sock+1, &fds, NULL, NULL, timeout);
286 if (ret < 0 && errno == EINTR) return IO_RETRY; 296 if (ret < 0 && errno == EINTR) return IO_RETRY;
287 if (ret == 0) return IO_TIMEOUT; 297 if (ret == 0) return IO_TIMEOUT;
288 else return IO_DONE; 298 else return IO_DONE;
@@ -315,53 +325,98 @@ void sock_setnonblocking(p_sock ps)
315/*-------------------------------------------------------------------------*\ 325/*-------------------------------------------------------------------------*\
316* Error translation functions 326* Error translation functions
317\*-------------------------------------------------------------------------*/ 327\*-------------------------------------------------------------------------*/
328/* return error messages for the known errors reported by gethostbyname */
318const char *sock_hoststrerror(void) 329const char *sock_hoststrerror(void)
319{ 330{
320 switch (h_errno) { 331 switch (h_errno) {
321 case HOST_NOT_FOUND: return "host not found"; 332 case HOST_NOT_FOUND: return "host not found";
322 case NO_ADDRESS: return "unable to resolve host name"; 333 case NO_ADDRESS: return "valid host but no ip found";
323 case NO_RECOVERY: return "name server error"; 334 case NO_RECOVERY: return "name server error";
324 case TRY_AGAIN: return "name server unavailable, try again later"; 335 case TRY_AGAIN: return "name server unavailable, try again later";
325 default: return "unknown error"; 336 default: return "unknown error";
326 } 337 }
327} 338}
328 339
329static const char *sock_createstrerror(void) 340/* return error messages for the known errors reported by socket */
341static const char *sock_createstrerror(int err)
330{ 342{
331 switch (errno) { 343 switch (err) {
344 case EPROTONOSUPPORT: return "protocol not supported";
332 case EACCES: return "access denied"; 345 case EACCES: return "access denied";
333 case EMFILE: return "descriptor table is full"; 346 case EMFILE: return "process file table is full";
334 case ENFILE: return "too many open files"; 347 case ENFILE: return "kernel file table is full";
348 case EINVAL: return "unknown protocol or family";
335 case ENOBUFS: return "insuffucient buffer space"; 349 case ENOBUFS: return "insuffucient buffer space";
336 default: return "unknown error"; 350 default: return "unknown error";
337 } 351 }
338} 352}
339 353
340static const char *sock_bindstrerror(void) 354/* return error messages for the known errors reported by accept */
355static const char *sock_acceptstrerror(int err)
341{ 356{
342 switch (errno) { 357 switch (err) {
358 case EWOULDBLOCK: return io_strerror(IO_RETRY);
343 case EBADF: return "invalid descriptor"; 359 case EBADF: return "invalid descriptor";
344 case EINVAL: return "socket already bound"; 360 case ENOBUFS: case ENOMEM: return "insuffucient buffer space";
345 case EACCES: return "access denied"; 361 case ENOTSOCK: return "descriptor not a socket";
346 case ENOTSOCK: return "not a socket descriptor"; 362 case EOPNOTSUPP: return "not supported";
363 case EINTR: return "call interrupted";
364 case ECONNABORTED: return "connection aborted";
365 case EINVAL: return "not listening";
366 case EMFILE: return "process file table is full";
367 case ENFILE: return "kernel file table is full";
368 case EFAULT: return "invalid memory address";
369 default: return "unknown error";
370 }
371}
372
373
374/* return error messages for the known errors reported by bind */
375static const char *sock_bindstrerror(int err)
376{
377 switch (err) {
378 case EBADF: return "invalid descriptor";
379 case ENOTSOCK: return "descriptor not a socket";
380 case EADDRNOTAVAIL: return "address unavailable in local host";
347 case EADDRINUSE: return "address already in use"; 381 case EADDRINUSE: return "address already in use";
348 case EADDRNOTAVAIL: return "address unavailable"; 382 case EINVAL: return "already bound";
383 case EACCES: return "access denied";
384 case EFAULT: return "invalid memory address";
349 case ENOMEM: return "out of memory"; 385 case ENOMEM: return "out of memory";
350 default: return "unknown error"; 386 default: return "unknown error";
351 } 387 }
352} 388}
353 389
354static const char *sock_connectstrerror(void) 390/* return error messages for the known errors reported by listen */
391static const char *sock_listenstrerror(int err)
355{ 392{
356 switch (errno) { 393 switch (err) {
394 case EADDRINUSE: return "local address already in use";
357 case EBADF: return "invalid descriptor"; 395 case EBADF: return "invalid descriptor";
358 case ENOTSOCK: return "not a socket descriptor"; 396 case ENOTSOCK: return "descriptor not a socket";
359 case EADDRNOTAVAIL: return "address not availabe"; 397 case EOPNOTSUPP: return "not supported";
360 case ETIMEDOUT: return "connection timed out"; 398 default: return "unknown error";
399 }
400}
401
402/* return error messages for the known errors reported by connect */
403static const char *sock_connectstrerror(int err)
404{
405 switch (err) {
406 case EBADF: return "invalid descriptor";
407 case EFAULT: return "invalid memory address";
408 case ENOTSOCK: return "descriptor not a socket";
409 case EADDRNOTAVAIL: return "address not available in local host";
410 case EISCONN: return "already connected";
361 case ECONNREFUSED: return "connection refused"; 411 case ECONNREFUSED: return "connection refused";
362 case EACCES: return "access denied"; 412 case ETIMEDOUT: return io_strerror(IO_TIMEOUT);
363 case ENETUNREACH: return "network is unreachable"; 413 case ENETUNREACH: return "network is unreachable";
364 case EADDRINUSE: return "address already in use"; 414 case EADDRINUSE: return "local address already in use";
415 case EINPROGRESS: return "would block";
416 case EALREADY: return "connect already in progress";
417 case EAGAIN: return "not enough free ports";
418 case EAFNOSUPPORT: return "address family not supported";
419 case EPERM: return "broadcast not enabled or firewall block";
365 default: return "unknown error"; 420 default: return "unknown error";
366 } 421 }
367} 422}
diff --git a/src/wsocket.c b/src/wsocket.c
index f834503..f33e154 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -15,9 +15,11 @@
15 15
16#include "socket.h" 16#include "socket.h"
17 17
18static const char *sock_createstrerror(void); 18static const char *sock_createstrerror(int err);
19static const char *sock_bindstrerror(void); 19static const char *sock_bindstrerror(int err);
20static const char *sock_connectstrerror(void); 20static const char *sock_connectstrerror(int err);
21static const char *sock_acceptstrerror(int err);
22static const char *sock_listenstrerror(int err);
21 23
22/*-------------------------------------------------------------------------*\ 24/*-------------------------------------------------------------------------*\
23* Initializes module 25* Initializes module
@@ -36,11 +38,23 @@ int sock_open(void)
36} 38}
37 39
38/*-------------------------------------------------------------------------*\ 40/*-------------------------------------------------------------------------*\
41* Select with int timeout in ms
42\*-------------------------------------------------------------------------*/
43int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout)
44{
45 struct timeval tv;
46 tv.tv_sec = timeout / 1000;
47 tv.tv_usec = (timeout % 1000) * 1000;
48 return select(n, rfds, wfds, efds, timeout >= 0? &tv: NULL);
49}
50
51/*-------------------------------------------------------------------------*\
39* Close and inutilize socket 52* Close and inutilize socket
40\*-------------------------------------------------------------------------*/ 53\*-------------------------------------------------------------------------*/
41void sock_destroy(p_sock ps) 54void sock_destroy(p_sock ps)
42{ 55{
43 if (*ps != SOCK_INVALID) { 56 if (*ps != SOCK_INVALID) {
57 sock_setblocking(ps); /* close can take a long time on WIN32 */
44 closesocket(*ps); 58 closesocket(*ps);
45 *ps = SOCK_INVALID; 59 *ps = SOCK_INVALID;
46 } 60 }
@@ -51,7 +65,9 @@ void sock_destroy(p_sock ps)
51\*-------------------------------------------------------------------------*/ 65\*-------------------------------------------------------------------------*/
52void sock_shutdown(p_sock ps, int how) 66void sock_shutdown(p_sock ps, int how)
53{ 67{
68 sock_setblocking(ps);
54 shutdown(*ps, how); 69 shutdown(*ps, how);
70 sock_setnonblocking(ps);
55} 71}
56 72
57/*-------------------------------------------------------------------------*\ 73/*-------------------------------------------------------------------------*\
@@ -61,10 +77,11 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol)
61{ 77{
62 int val = 1; 78 int val = 1;
63 t_sock sock = socket(domain, type, protocol); 79 t_sock sock = socket(domain, type, protocol);
64 if (sock == SOCK_INVALID) return sock_createstrerror(); 80 if (sock == SOCK_INVALID)
81 return sock_createstrerror(WSAGetLastError());
65 *ps = sock; 82 *ps = sock;
66 sock_setnonblocking(ps);
67 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); 83 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
84 sock_setnonblocking(ps);
68 return NULL; 85 return NULL;
69} 86}
70 87
@@ -75,7 +92,6 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
75{ 92{
76 t_sock sock = *ps; 93 t_sock sock = *ps;
77 int err, timeout = tm_getretry(tm); 94 int err, timeout = tm_getretry(tm);
78 struct timeval tv;
79 fd_set efds, wfds; 95 fd_set efds, wfds;
80 /* don't call on closed socket */ 96 /* don't call on closed socket */
81 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); 97 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED);
@@ -84,27 +100,24 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
84 /* if no error, we're done */ 100 /* if no error, we're done */
85 if (err == 0) return NULL; 101 if (err == 0) return NULL;
86 /* make sure the system is trying to connect */ 102 /* make sure the system is trying to connect */
87 if (WSAGetLastError() != WSAEWOULDBLOCK) return sock_connectstrerror(); 103 err = WSAGetLastError();
104 if (err != WSAEWOULDBLOCK) return sock_connectstrerror(err);
88 /* wait for a timeout or for the system's answer */ 105 /* wait for a timeout or for the system's answer */
89 tv.tv_sec = timeout / 1000;
90 tv.tv_usec = (timeout % 1000) * 1000;
91 FD_ZERO(&wfds); FD_SET(sock, &wfds); 106 FD_ZERO(&wfds); FD_SET(sock, &wfds);
92 FD_ZERO(&efds); FD_SET(sock, &efds); 107 FD_ZERO(&efds); FD_SET(sock, &efds);
93 /* we run select to wait */ 108 /* we run select to wait */
94 err = select(0, NULL, &wfds, &efds, timeout >= 0? &tv: NULL); 109 err = sock_select(0, NULL, &wfds, &efds, timeout);
95 /* if select returned due to an event */ 110 /* if select returned due to an event */
96 if (err > 0 ) { 111 if (err > 0 ) {
97 /* if was in efds, we failed */ 112 /* if was in efds, we failed */
98 if (FD_ISSET(sock,&efds) || !FD_ISSET(sock,&wfds)) { 113 if (FD_ISSET(sock, &efds)) {
99 int why; 114 int why, len = sizeof(why);
100 int len = sizeof(why);
101 /* find out why we failed */ 115 /* find out why we failed */
102 getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len); 116 getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len);
103 WSASetLastError(why); 117 return sock_connectstrerror(why);
104 return sock_connectstrerror(); 118 /* otherwise it must be in wfds, so we succeeded */
105 /* if was in wfds, we succeeded */
106 } else return NULL; 119 } else return NULL;
107 /* if nothing happened, we timed out */ 120 /* if no event happened, we timed out */
108 } else return io_strerror(IO_TIMEOUT); 121 } else return io_strerror(IO_TIMEOUT);
109} 122}
110 123
@@ -113,44 +126,60 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
113\*-------------------------------------------------------------------------*/ 126\*-------------------------------------------------------------------------*/
114const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) 127const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
115{ 128{
116 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); 129 const char *err = NULL;
117 else return NULL; 130 sock_setblocking(ps);
131 if (bind(*ps, addr, addr_len) < 0)
132 err = sock_bindstrerror(WSAGetLastError());
133 sock_setnonblocking(ps);
134 return err;
118} 135}
119 136
120/*-------------------------------------------------------------------------*\ 137/*-------------------------------------------------------------------------*\
121* 138*
122\*-------------------------------------------------------------------------*/ 139\*-------------------------------------------------------------------------*/
123void sock_listen(p_sock ps, int backlog) 140const char *sock_listen(p_sock ps, int backlog)
124{ 141{
125 listen(*ps, backlog); 142 const char *err = NULL;
143 sock_setblocking(ps);
144 if (listen(*ps, backlog) < 0)
145 err = sock_listenstrerror(WSAGetLastError());
146 sock_setnonblocking(ps);
147 return err;
126} 148}
127 149
128/*-------------------------------------------------------------------------*\ 150/*-------------------------------------------------------------------------*\
129* Accept with timeout 151* Accept with timeout
130\*-------------------------------------------------------------------------*/ 152\*-------------------------------------------------------------------------*/
131int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, p_tm tm) 153const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
154 socklen_t *addr_len, p_tm tm)
132{ 155{
133 t_sock sock = *ps; 156 t_sock sock = *ps;
134 SA dummy_addr; 157 SA dummy_addr;
135 socklen_t dummy_len = sizeof(dummy_addr); 158 socklen_t dummy_len = sizeof(dummy_addr);
136 if (sock == SOCK_INVALID) return IO_CLOSED; 159 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED);
137 if (!addr) addr = &dummy_addr; 160 if (!addr) addr = &dummy_addr;
138 if (!addr_len) addr_len = &dummy_len; 161 if (!addr_len) addr_len = &dummy_len;
139 for (;;) { 162 for (;;) {
163 fd_set rfds;
140 int timeout = tm_getretry(tm); 164 int timeout = tm_getretry(tm);
141 struct timeval tv; 165 int err;
142 fd_set fds; 166 /* try to get client socket */
143 *pa = accept(sock, addr, addr_len); 167 *pa = accept(sock, addr, addr_len);
144 if (*pa != SOCK_INVALID) return IO_DONE; 168 /* if return is valid, we are done */
145 if (timeout == 0) return IO_TIMEOUT; 169 if (*pa != SOCK_INVALID) return NULL;
146 tv.tv_sec = timeout / 1000; 170 /* optimization */
147 tv.tv_usec = (timeout % 1000) * 1000; 171 if (timeout == 0) return io_strerror(IO_TIMEOUT);
148 FD_ZERO(&fds); 172 /* otherwise find out why we failed */
149 FD_SET(sock, &fds); 173 err = WSAGetLastError();
150 /* call select just to avoid busy-wait. */ 174 /* if we failed because there was no connectoin, keep trying*/
151 select(0, &fds, NULL, NULL, timeout >= 0? &tv: NULL); 175 if (err != WSAEWOULDBLOCK) return sock_acceptstrerror(err);
176 /* call select to avoid busy wait */
177 FD_ZERO(&rfds);
178 FD_SET(sock, &rfds);
179 err = sock_select(0, &rfds, NULL, NULL, timeout);
180 if (err <= 0) return io_strerror(IO_TIMEOUT);
152 } 181 }
153 return IO_TIMEOUT; /* can't get here */ 182 return io_strerror(IO_TIMEOUT); /* can't get here */
154} 183}
155 184
156/*-------------------------------------------------------------------------*\ 185/*-------------------------------------------------------------------------*\
@@ -172,13 +201,10 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
172 *sent = 0; 201 *sent = 0;
173 /* run select to avoid busy wait */ 202 /* run select to avoid busy wait */
174 if (WSAGetLastError() == WSAEWOULDBLOCK) { 203 if (WSAGetLastError() == WSAEWOULDBLOCK) {
175 struct timeval tv;
176 fd_set fds; 204 fd_set fds;
177 tv.tv_sec = timeout / 1000;
178 tv.tv_usec = (timeout % 1000) * 1000;
179 FD_ZERO(&fds); 205 FD_ZERO(&fds);
180 FD_SET(sock, &fds); 206 FD_SET(sock, &fds);
181 ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); 207 ret = sock_select(0, NULL, &fds, NULL, timeout);
182 /* tell the caller to call us again because there is more data */ 208 /* tell the caller to call us again because there is more data */
183 if (ret > 0) return IO_DONE; 209 if (ret > 0) return IO_DONE;
184 /* tell the caller there was no data before timeout */ 210 /* tell the caller there was no data before timeout */
@@ -211,13 +237,10 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
211 *sent = 0; 237 *sent = 0;
212 /* run select to avoid busy wait */ 238 /* run select to avoid busy wait */
213 if (WSAGetLastError() == WSAEWOULDBLOCK) { 239 if (WSAGetLastError() == WSAEWOULDBLOCK) {
214 struct timeval tv;
215 fd_set fds; 240 fd_set fds;
216 tv.tv_sec = timeout / 1000;
217 tv.tv_usec = (timeout % 1000) * 1000;
218 FD_ZERO(&fds); 241 FD_ZERO(&fds);
219 FD_SET(sock, &fds); 242 FD_SET(sock, &fds);
220 ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); 243 ret = sock_select(0, NULL, &fds, NULL, timeout);
221 /* tell the caller to call us again because there is more data */ 244 /* tell the caller to call us again because there is more data */
222 if (ret > 0) return IO_DONE; 245 if (ret > 0) return IO_DONE;
223 /* tell the caller there was no data before timeout */ 246 /* tell the caller there was no data before timeout */
@@ -241,16 +264,13 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
241 if (sock == SOCK_INVALID) return IO_CLOSED; 264 if (sock == SOCK_INVALID) return IO_CLOSED;
242 taken = recv(sock, data, (int) count, 0); 265 taken = recv(sock, data, (int) count, 0);
243 if (taken <= 0) { 266 if (taken <= 0) {
244 struct timeval tv;
245 fd_set fds; 267 fd_set fds;
246 int ret; 268 int ret;
247 *got = 0; 269 *got = 0;
248 if (taken == 0) return IO_CLOSED; 270 if (taken == 0) return IO_CLOSED;
249 tv.tv_sec = timeout / 1000;
250 tv.tv_usec = (timeout % 1000) * 1000;
251 FD_ZERO(&fds); 271 FD_ZERO(&fds);
252 FD_SET(sock, &fds); 272 FD_SET(sock, &fds);
253 ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 273 ret = sock_select(0, &fds, NULL, NULL, timeout);
254 if (ret > 0) return IO_DONE; 274 if (ret > 0) return IO_DONE;
255 else return IO_TIMEOUT; 275 else return IO_TIMEOUT;
256 } else { 276 } else {
@@ -270,16 +290,13 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
270 if (sock == SOCK_INVALID) return IO_CLOSED; 290 if (sock == SOCK_INVALID) return IO_CLOSED;
271 taken = recvfrom(sock, data, (int) count, 0, addr, addr_len); 291 taken = recvfrom(sock, data, (int) count, 0, addr, addr_len);
272 if (taken <= 0) { 292 if (taken <= 0) {
273 struct timeval tv;
274 fd_set fds; 293 fd_set fds;
275 int ret; 294 int ret;
276 *got = 0; 295 *got = 0;
277 if (taken == 0) return IO_CLOSED; 296 if (taken == 0) return IO_CLOSED;
278 tv.tv_sec = timeout / 1000;
279 tv.tv_usec = (timeout % 1000) * 1000;
280 FD_ZERO(&fds); 297 FD_ZERO(&fds);
281 FD_SET(sock, &fds); 298 FD_SET(sock, &fds);
282 ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 299 ret = sock_select(0, &fds, NULL, NULL, timeout);
283 if (ret > 0) return IO_DONE; 300 if (ret > 0) return IO_DONE;
284 else return IO_TIMEOUT; 301 else return IO_TIMEOUT;
285 } else { 302 } else {
@@ -309,51 +326,117 @@ void sock_setnonblocking(p_sock ps)
309/*-------------------------------------------------------------------------*\ 326/*-------------------------------------------------------------------------*\
310* Error translation functions 327* Error translation functions
311\*-------------------------------------------------------------------------*/ 328\*-------------------------------------------------------------------------*/
329/* return error messages for the known errors reported by gethostbyname */
312const char *sock_hoststrerror(void) 330const char *sock_hoststrerror(void)
313{ 331{
314 switch (WSAGetLastError()) { 332 switch (WSAGetLastError()) {
315 case HOST_NOT_FOUND: return "host not found"; 333 case WSANOTINITIALISED: return "not initialized";
316 case NO_ADDRESS: return "unable to resolve host name"; 334 case WSAENETDOWN: return "network is down";
317 case NO_RECOVERY: return "name server error"; 335 case WSAHOST_NOT_FOUND: return "host not found";
318 case TRY_AGAIN: return "name server unavailable, try again later."; 336 case WSATRY_AGAIN: return "name server unavailable, try again later";
337 case WSANO_RECOVERY: return "name server error";
338 case WSANO_DATA: return "host not found";
339 case WSAEINPROGRESS: return "another call in progress";
340 case WSAEFAULT: return "invalid memory address";
341 case WSAEINTR: return "call interrupted";
319 default: return "unknown error"; 342 default: return "unknown error";
320 } 343 }
321} 344}
322 345
323static const char *sock_createstrerror(void) 346/* return error messages for the known errors reported by socket */
347static const char *sock_createstrerror(int err)
324{ 348{
325 switch (WSAGetLastError()) { 349 switch (err) {
326 case WSANOTINITIALISED: return "not initialized"; 350 case WSANOTINITIALISED: return "not initialized";
327 case WSAENETDOWN: return "network is down"; 351 case WSAENETDOWN: return "network is down";
352 case WSAEAFNOSUPPORT: return "address family not supported";
353 case WSAEINPROGRESS: return "another call in progress";
328 case WSAEMFILE: return "descriptor table is full"; 354 case WSAEMFILE: return "descriptor table is full";
329 case WSAENOBUFS: return "insufficient buffer space"; 355 case WSAENOBUFS: return "insufficient buffer space";
356 case WSAEPROTONOSUPPORT: return "protocol not supported";
357 case WSAEPROTOTYPE: return "wrong protocol type";
358 case WSAESOCKTNOSUPPORT: return "socket type not supported by family";
330 default: return "unknown error"; 359 default: return "unknown error";
331 } 360 }
332} 361}
333 362
334static const char *sock_bindstrerror(void) 363/* return error messages for the known errors reported by accept */
364static const char *sock_acceptstrerror(int err)
335{ 365{
336 switch (WSAGetLastError()) { 366 switch (err) {
337 case WSANOTINITIALISED: return "not initialized"; 367 case WSANOTINITIALISED: return "not initialized";
338 case WSAENETDOWN: return "network is down"; 368 case WSAENETDOWN: return "network is down";
339 case WSAEADDRINUSE: return "address already in use"; 369 case WSAEFAULT: return "invalid memory address";
340 case WSAEINVAL: return "socket already bound"; 370 case WSAEINTR: return "call interrupted";
341 case WSAENOBUFS: return "too many connections"; 371 case WSAEINPROGRESS: return "another call in progress";
342 case WSAEFAULT: return "invalid address"; 372 case WSAEINVAL: return "not listening";
343 case WSAENOTSOCK: return "not a socket descriptor"; 373 case WSAEMFILE: return "descriptor table is full";
374 case WSAENOBUFS: return "insufficient buffer space";
375 case WSAENOTSOCK: return "descriptor not a socket";
376 case WSAEOPNOTSUPP: return "not supported";
377 case WSAEWOULDBLOCK: return "call would block";
344 default: return "unknown error"; 378 default: return "unknown error";
345 } 379 }
346} 380}
347 381
348static const char *sock_connectstrerror(void) 382/* return error messages for the known errors reported by bind */
383static const char *sock_bindstrerror(int err)
349{ 384{
350 switch (WSAGetLastError()) { 385 switch (err) {
351 case WSANOTINITIALISED: return "not initialized"; 386 case WSANOTINITIALISED: return "not initialized";
352 case WSAENETDOWN: return "network is down"; 387 case WSAENETDOWN: return "network is down";
388 case WSAEACCES: return "broadcast not enabled for socket";
353 case WSAEADDRINUSE: return "address already in use"; 389 case WSAEADDRINUSE: return "address already in use";
354 case WSAEADDRNOTAVAIL: return "address unavailable"; 390 case WSAEADDRNOTAVAIL: return "address not available in local host";
391 case WSAEFAULT: return "invalid memory address";
392 case WSAEINPROGRESS: return "another call in progress";
393 case WSAEINVAL: return "already bound";
394 case WSAENOBUFS: return "insuficient buffer space";
395 case WSAENOTSOCK: return "descriptor not a socket";
396 default: return "unknown error";
397 }
398
399}
400
401/* return error messages for the known errors reported by listen */
402static const char *sock_listenstrerror(int err)
403{
404 switch (err) {
405 case WSANOTINITIALISED: return "not initialized";
406 case WSAENETDOWN: return "network is down";
407 case WSAEADDRINUSE: return "local address already in use";
408 case WSAEINPROGRESS: return "another call in progress";
409 case WSAEINVAL: return "not bound";
410 case WSAEISCONN: return "already connected";
411 case WSAEMFILE: return "descriptor table is full";
412 case WSAENOBUFS: return "insuficient buffer space";
413 case WSAENOTSOCK: return "descriptor not a socket";
414 case WSAEOPNOTSUPP: return "not supported";
415 default: return "unknown error";
416 }
417}
418
419/* return error messages for the known errors reported by connect */
420static const char *sock_connectstrerror(int err)
421{
422 switch (err) {
423 case WSANOTINITIALISED: return "not initialized";
424 case WSAENETDOWN: return "network is down";
425 case WSAEADDRINUSE: return "local address already in use";
426 case WSAEINTR: return "call interrupted";
427 case WSAEINPROGRESS: return "another call in progress";
428 case WSAEALREADY: return "connect already in progress";
429 case WSAEADDRNOTAVAIL: return "invalid remote address";
430 case WSAEAFNOSUPPORT: return "address family not supported";
355 case WSAECONNREFUSED: return "connection refused"; 431 case WSAECONNREFUSED: return "connection refused";
432 case WSAEFAULT: return "invalid memory address";
433 case WSAEINVAL: return "socket is listening";
434 case WSAEISCONN: return "socket already connected";
356 case WSAENETUNREACH: return "network is unreachable"; 435 case WSAENETUNREACH: return "network is unreachable";
436 case WSAENOTSOCK: return "descriptor not a socket";
437 case WSAETIMEDOUT: return io_strerror(IO_TIMEOUT);
438 case WSAEWOULDBLOCK: return "would block";
439 case WSAEACCES: return "broadcast not enabled";
357 default: return "unknown error"; 440 default: return "unknown error";
358 } 441 }
359} 442}
diff --git a/test/testclnt.lua b/test/testclnt.lua
index 6dccd0c..beb0157 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -117,7 +117,6 @@ function test_mixed(len)
117 local p3 = "raw " .. string.rep("z", inter) .. "bytes" 117 local p3 = "raw " .. string.rep("z", inter) .. "bytes"
118 local p4 = "end" .. string.rep("w", inter) .. "bytes" 118 local p4 = "end" .. string.rep("w", inter) .. "bytes"
119 local bp1, bp2, bp3, bp4 119 local bp1, bp2, bp3, bp4
120 pass(len .. " byte(s) patterns")
121remote (string.format("str = data:receive(%d)", 120remote (string.format("str = data:receive(%d)",
122 string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4))) 121 string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
123 sent, err = data:send(p1, p2, p3, p4) 122 sent, err = data:send(p1, p2, p3, p4)
@@ -137,7 +136,6 @@ function test_asciiline(len)
137 str = string.rep("x", math.mod(len, 10)) 136 str = string.rep("x", math.mod(len, 10))
138 str10 = string.rep("aZb.c#dAe?", math.floor(len/10)) 137 str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
139 str = str .. str10 138 str = str .. str10
140 pass(len .. " byte(s) line")
141remote "str = data:receive()" 139remote "str = data:receive()"
142 sent, err = data:send(str, "\n") 140 sent, err = data:send(str, "\n")
143 if err then fail(err) end 141 if err then fail(err) end
@@ -156,7 +154,6 @@ function test_rawline(len)
156 str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100), 154 str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
157 math.floor(len/10)) 155 math.floor(len/10))
158 str = str .. str10 156 str = str .. str10
159 pass(len .. " byte(s) line")
160remote "str = data:receive()" 157remote "str = data:receive()"
161 sent, err = data:send(str, "\n") 158 sent, err = data:send(str, "\n")
162 if err then fail(err) end 159 if err then fail(err) end
@@ -174,7 +171,6 @@ function test_raw(len)
174 local s1, s2, back, err 171 local s1, s2, back, err
175 s1 = string.rep("x", half) 172 s1 = string.rep("x", half)
176 s2 = string.rep("y", len-half) 173 s2 = string.rep("y", len-half)
177 pass(len .. " byte(s) block")
178remote (string.format("str = data:receive(%d)", len)) 174remote (string.format("str = data:receive(%d)", len))
179 sent, err = data:send(s1) 175 sent, err = data:send(s1)
180 if err then fail(err) end 176 if err then fail(err) end
@@ -271,12 +267,10 @@ end
271function empty_connect() 267function empty_connect()
272 reconnect() 268 reconnect()
273 if data then data:close() data = nil end 269 if data then data:close() data = nil end
274print("before remote")
275 remote [[ 270 remote [[
276 if data then data:close() data = nil end 271 if data then data:close() data = nil end
277 data = server:accept() 272 data = server:accept()
278 ]] 273 ]]
279print("after remote")
280 data, err = socket.connect("", port) 274 data, err = socket.connect("", port)
281 if not data then 275 if not data then
282 pass("ok") 276 pass("ok")
@@ -286,7 +280,7 @@ end
286 280
287------------------------------------------------------------------------ 281------------------------------------------------------------------------
288function isclosed(c) 282function isclosed(c)
289 return c:fd() == -1 or c:fd() == (2^32-1) 283 return c:getfd() == -1 or c:getfd() == (2^32-1)
290end 284end
291 285
292function active_close() 286function active_close()
@@ -354,13 +348,14 @@ end
354 348
355------------------------------------------------------------------------ 349------------------------------------------------------------------------
356function accept_timeout() 350function accept_timeout()
351 io.write("accept with timeout (if it hangs, it failed): ")
357 local s, e = socket.bind("*", 0, 0) 352 local s, e = socket.bind("*", 0, 0)
358 assert(s, e) 353 assert(s, e)
359 local t = socket.time() 354 local t = socket.time()
360 s:settimeout(1) 355 s:settimeout(1)
361 local c, e = s:accept() 356 local c, e = s:accept()
362 assert(not c, "should not accept") 357 assert(not c, "should not accept")
363 assert(e == "timeout", "wrong error message") 358 assert(e == "timeout", string.format("wrong error message (%s)", e))
364 t = socket.time() - t 359 t = socket.time() - t
365 assert(t < 2, string.format("took to long to give up (%gs)", t)) 360 assert(t < 2, string.format("took to long to give up (%gs)", t))
366 s:close() 361 s:close()
@@ -369,22 +364,51 @@ end
369 364
370------------------------------------------------------------------------ 365------------------------------------------------------------------------
371function connect_timeout() 366function connect_timeout()
367 io.write("connect with timeout (if it hangs, it failed): ")
372 local t = socket.time() 368 local t = socket.time()
373 local c, e = socket.tcp() 369 local c, e = socket.tcp()
374 assert(c, e) 370 assert(c, e)
375 c:settimeout(0.1) 371 c:settimeout(0.1)
376 local r, e = c:connect("ibere.tecgraf.puc-rio.br", 80) 372 local r, e = c:connect("ibere.tecgraf.puc-rio.br", 80)
377 if r or e ~= "timeout" then 373 assert(not r, "should not connect")
378 print("wrong error message (this test is flaky anyways)") 374 assert(e == "timeout", e)
379 end 375 assert(socket.time() - t < 2, "took to long to give up")
380 if socket.time() - t > 1 then
381 print("took to long to give up")
382 end
383 print("whatever")
384 c:close() 376 c:close()
385end 377end
386 378
387------------------------------------------------------------------------ 379------------------------------------------------------------------------
380function accept_errors()
381 io.write("not listenning: ")
382 local d, e = socket.bind("*", 0)
383 assert(d, e);
384 local c, e = socket.tcp();
385 assert(c, e);
386 d:setfd(c:getfd())
387 local r, e = d:accept()
388 assert(not r and e == "not listening", e)
389 print("ok")
390 io.write("not supported: ")
391 local c, e = socket.udp()
392 assert(c, e);
393 d:setfd(c:getfd())
394 local r, e = d:accept()
395 assert(not r and e == "not supported", e)
396 print("ok")
397end
398
399------------------------------------------------------------------------
400function connect_errors()
401 io.write("connection refused: ")
402 local c, e = socket.connect("localhost", 1);
403 assert(not c and e == "connection refused", e)
404 print("ok")
405 io.write("host not found: ")
406 local c, e = socket.connect("not.exist.com", 1);
407 assert(not c and e == "host not found", e)
408 print("ok")
409end
410
411------------------------------------------------------------------------
388function rebind_test() 412function rebind_test()
389 local c = socket.bind("localhost", 0) 413 local c = socket.bind("localhost", 0)
390 local i, p = c:getsockname() 414 local i, p = c:getsockname()
@@ -400,40 +424,44 @@ end
400------------------------------------------------------------------------ 424------------------------------------------------------------------------
401test("method registration") 425test("method registration")
402test_methods(socket.tcp(), { 426test_methods(socket.tcp(), {
403 "connect", 427 "accept",
404 "send",
405 "receive",
406 "bind", 428 "bind",
407 "accept", 429 "close",
408 "setpeername", 430 "connect",
409 "setsockname",
410 "getpeername", 431 "getpeername",
411 "getsockname", 432 "getsockname",
433 "listen",
434 "receive",
435 "send",
412 "setoption", 436 "setoption",
437 "setpeername",
438 "setsockname",
413 "settimeout", 439 "settimeout",
414 "shutdown", 440 "shutdown",
415 "close",
416}) 441})
442
417test_methods(socket.udp(), { 443test_methods(socket.udp(), {
444 "close",
418 "getpeername", 445 "getpeername",
419 "getsockname", 446 "getsockname",
420 "setsockname",
421 "setpeername",
422 "send",
423 "sendto",
424 "receive", 447 "receive",
425 "receivefrom", 448 "receivefrom",
449 "send",
450 "sendto",
426 "setoption", 451 "setoption",
452 "setpeername",
453 "setsockname",
427 "settimeout", 454 "settimeout",
428 "shutdown", 455 "shutdown",
429 "close",
430}) 456})
431 457
432test("select function") 458test("select function")
433test_selectbugs() 459test_selectbugs()
434 460
435test("empty host connect: ") 461test("connect function")
462connect_timeout()
436empty_connect() 463empty_connect()
464connect_errors()
437 465
438test("rebinding: ") 466test("rebinding: ")
439rebind_test() 467rebind_test()
@@ -444,11 +472,10 @@ active_close()
444test("closed connection detection: ") 472test("closed connection detection: ")
445test_closed() 473test_closed()
446 474
447test("accept with timeout (if it hangs, it failed:)") 475test("accept function: ")
448accept_timeout() 476accept_timeout()
477accept_errors()
449 478
450test("connect with timeout (if it hangs, it failed:)")
451connect_timeout()
452 479
453test("mixed patterns") 480test("mixed patterns")
454test_mixed(1) 481test_mixed(1)