aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
8 files changed, 361 insertions, 163 deletions
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}