aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-07-01 03:32:09 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-07-01 03:32:09 +0000
commit7115c12fbc9aae1cd46fdf049697a27fb996181a (patch)
tree2e918f54f729766701aabdef488a6461bc623da1 /src
parent7aaba59909e8527190694285f56ca68772c97f6a (diff)
downloadluasocket-7115c12fbc9aae1cd46fdf049697a27fb996181a.tar.gz
luasocket-7115c12fbc9aae1cd46fdf049697a27fb996181a.tar.bz2
luasocket-7115c12fbc9aae1cd46fdf049697a27fb996181a.zip
Moving on to beta2.
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c68
-rw-r--r--src/io.c20
-rw-r--r--src/io.h22
-rw-r--r--src/select.c11
-rw-r--r--src/socket.h14
-rw-r--r--src/tcp.c6
-rw-r--r--src/timeout.c73
-rw-r--r--src/timeout.h16
-rw-r--r--src/udp.c105
-rw-r--r--src/usocket.c334
-rw-r--r--src/usocket.h6
11 files changed, 282 insertions, 393 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 60e42ae..aa50db0 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -33,8 +33,7 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent);
33/*-------------------------------------------------------------------------*\ 33/*-------------------------------------------------------------------------*\
34* Initializes module 34* Initializes module
35\*-------------------------------------------------------------------------*/ 35\*-------------------------------------------------------------------------*/
36int buf_open(lua_State *L) 36int buf_open(lua_State *L) {
37{
38 (void) L; 37 (void) L;
39 return 0; 38 return 0;
40} 39}
@@ -42,8 +41,7 @@ int buf_open(lua_State *L)
42/*-------------------------------------------------------------------------*\ 41/*-------------------------------------------------------------------------*\
43* Initializes C structure 42* Initializes C structure
44\*-------------------------------------------------------------------------*/ 43\*-------------------------------------------------------------------------*/
45void buf_init(p_buf buf, p_io io, p_tm tm) 44void buf_init(p_buf buf, p_io io, p_tm tm) {
46{
47 buf->first = buf->last = 0; 45 buf->first = buf->last = 0;
48 buf->io = io; 46 buf->io = io;
49 buf->tm = tm; 47 buf->tm = tm;
@@ -52,13 +50,11 @@ void buf_init(p_buf buf, p_io io, p_tm tm)
52/*-------------------------------------------------------------------------*\ 50/*-------------------------------------------------------------------------*\
53* object:send() interface 51* object:send() interface
54\*-------------------------------------------------------------------------*/ 52\*-------------------------------------------------------------------------*/
55int buf_meth_send(lua_State *L, p_buf buf) 53int buf_meth_send(lua_State *L, p_buf buf) {
56{
57 int top = lua_gettop(L); 54 int top = lua_gettop(L);
58 size_t total = 0; 55 size_t total = 0;
59 int arg, err = IO_DONE; 56 int arg, err = IO_DONE;
60 p_tm tm = buf->tm; 57 p_tm tm = tm_markstart(buf->tm);
61 tm_markstart(tm);
62 for (arg = 2; arg <= top; arg++) { /* first arg is socket object */ 58 for (arg = 2; arg <= top; arg++) { /* first arg is socket object */
63 size_t sent, count; 59 size_t sent, count;
64 const char *data = luaL_optlstring(L, arg, NULL, &count); 60 const char *data = luaL_optlstring(L, arg, NULL, &count);
@@ -69,7 +65,7 @@ int buf_meth_send(lua_State *L, p_buf buf)
69 /* check if there was an error */ 65 /* check if there was an error */
70 if (err != IO_DONE) { 66 if (err != IO_DONE) {
71 lua_pushnil(L); 67 lua_pushnil(L);
72 io_pusherror(L, err); 68 io_pusherror(L, buf->io, err);
73 lua_pushnumber(L, total); 69 lua_pushnumber(L, total);
74 } else { 70 } else {
75 lua_pushnumber(L, total); 71 lua_pushnumber(L, total);
@@ -78,7 +74,7 @@ int buf_meth_send(lua_State *L, p_buf buf)
78 } 74 }
79#ifdef LUASOCKET_DEBUG 75#ifdef LUASOCKET_DEBUG
80 /* push time elapsed during operation as the last return value */ 76 /* push time elapsed during operation as the last return value */
81 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); 77 lua_pushnumber(L, tm_gettime() - tm_getstart(tm));
82#endif 78#endif
83 return lua_gettop(L) - top; 79 return lua_gettop(L) - top;
84} 80}
@@ -86,13 +82,11 @@ int buf_meth_send(lua_State *L, p_buf buf)
86/*-------------------------------------------------------------------------*\ 82/*-------------------------------------------------------------------------*\
87* object:receive() interface 83* object:receive() interface
88\*-------------------------------------------------------------------------*/ 84\*-------------------------------------------------------------------------*/
89int buf_meth_receive(lua_State *L, p_buf buf) 85int buf_meth_receive(lua_State *L, p_buf buf) {
90{
91 int err = IO_DONE, top = lua_gettop(L); 86 int err = IO_DONE, top = lua_gettop(L);
92 p_tm tm = buf->tm; 87 p_tm tm = tm_markstart(buf->tm);
93 luaL_Buffer b; 88 luaL_Buffer b;
94 luaL_buffinit(L, &b); 89 luaL_buffinit(L, &b);
95 tm_markstart(tm);
96 /* receive all patterns */ 90 /* receive all patterns */
97 if (!lua_isnumber(L, 2)) { 91 if (!lua_isnumber(L, 2)) {
98 static const char *patternnames[] = {"*l", "*a", NULL}; 92 static const char *patternnames[] = {"*l", "*a", NULL};
@@ -107,7 +101,7 @@ int buf_meth_receive(lua_State *L, p_buf buf)
107 /* check if there was an error */ 101 /* check if there was an error */
108 if (err != IO_DONE) { 102 if (err != IO_DONE) {
109 luaL_pushresult(&b); 103 luaL_pushresult(&b);
110 io_pusherror(L, err); 104 io_pusherror(L, buf->io, err);
111 lua_pushvalue(L, -2); 105 lua_pushvalue(L, -2);
112 lua_pushnil(L); 106 lua_pushnil(L);
113 lua_replace(L, -4); 107 lua_replace(L, -4);
@@ -118,7 +112,7 @@ int buf_meth_receive(lua_State *L, p_buf buf)
118 } 112 }
119#ifdef LUASOCKET_DEBUG 113#ifdef LUASOCKET_DEBUG
120 /* push time elapsed during operation as the last return value */ 114 /* push time elapsed during operation as the last return value */
121 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); 115 lua_pushnumber(L, tm_gettime() - tm_getstart(tm));
122#endif 116#endif
123 return lua_gettop(L) - top; 117 return lua_gettop(L) - top;
124} 118}
@@ -126,8 +120,7 @@ int buf_meth_receive(lua_State *L, p_buf buf)
126/*-------------------------------------------------------------------------*\ 120/*-------------------------------------------------------------------------*\
127* Determines if there is any data in the read buffer 121* Determines if there is any data in the read buffer
128\*-------------------------------------------------------------------------*/ 122\*-------------------------------------------------------------------------*/
129int buf_isempty(p_buf buf) 123int buf_isempty(p_buf buf) {
130{
131 return buf->first >= buf->last; 124 return buf->first >= buf->last;
132} 125}
133 126
@@ -137,16 +130,14 @@ int buf_isempty(p_buf buf)
137/*-------------------------------------------------------------------------*\ 130/*-------------------------------------------------------------------------*\
138* Sends a block of data (unbuffered) 131* Sends a block of data (unbuffered)
139\*-------------------------------------------------------------------------*/ 132\*-------------------------------------------------------------------------*/
140static 133static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) {
141int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
142{
143 p_io io = buf->io; 134 p_io io = buf->io;
144 p_tm tm = buf->tm; 135 p_tm tm = buf->tm;
145 size_t total = 0; 136 size_t total = 0;
146 int err = IO_DONE; 137 int err = IO_DONE;
147 while (total < count && (err == IO_DONE || err == IO_RETRY)) { 138 while (total < count && err == IO_DONE) {
148 size_t done; 139 size_t done;
149 err = io->send(io->ctx, data+total, count-total, &done, tm_get(tm)); 140 err = io->send(io->ctx, data+total, count-total, &done, tm);
150 total += done; 141 total += done;
151 } 142 }
152 *sent = total; 143 *sent = total;
@@ -156,12 +147,10 @@ int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
156/*-------------------------------------------------------------------------*\ 147/*-------------------------------------------------------------------------*\
157* Reads a fixed number of bytes (buffered) 148* Reads a fixed number of bytes (buffered)
158\*-------------------------------------------------------------------------*/ 149\*-------------------------------------------------------------------------*/
159static 150static int recvraw(p_buf buf, size_t wanted, luaL_Buffer *b) {
160int recvraw(p_buf buf, size_t wanted, luaL_Buffer *b) 151 int err = IO_DONE;
161{
162 int err = IO_DONE;
163 size_t total = 0; 152 size_t total = 0;
164 while (total < wanted && (err == IO_DONE || err == IO_RETRY)) { 153 while (total < wanted && err == IO_DONE) {
165 size_t count; const char *data; 154 size_t count; const char *data;
166 err = buf_get(buf, &data, &count); 155 err = buf_get(buf, &data, &count);
167 count = MIN(count, wanted - total); 156 count = MIN(count, wanted - total);
@@ -175,11 +164,9 @@ int recvraw(p_buf buf, size_t wanted, luaL_Buffer *b)
175/*-------------------------------------------------------------------------*\ 164/*-------------------------------------------------------------------------*\
176* Reads everything until the connection is closed (buffered) 165* Reads everything until the connection is closed (buffered)
177\*-------------------------------------------------------------------------*/ 166\*-------------------------------------------------------------------------*/
178static 167static int recvall(p_buf buf, luaL_Buffer *b) {
179int recvall(p_buf buf, luaL_Buffer *b)
180{
181 int err = IO_DONE; 168 int err = IO_DONE;
182 while (err == IO_DONE || err == IO_RETRY) { 169 while (err == IO_DONE) {
183 const char *data; size_t count; 170 const char *data; size_t count;
184 err = buf_get(buf, &data, &count); 171 err = buf_get(buf, &data, &count);
185 luaL_addlstring(b, data, count); 172 luaL_addlstring(b, data, count);
@@ -193,11 +180,9 @@ int recvall(p_buf buf, luaL_Buffer *b)
193* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF 180* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
194* are not returned by the function and are discarded from the buffer 181* are not returned by the function and are discarded from the buffer
195\*-------------------------------------------------------------------------*/ 182\*-------------------------------------------------------------------------*/
196static 183static int recvline(p_buf buf, luaL_Buffer *b) {
197int recvline(p_buf buf, luaL_Buffer *b)
198{
199 int err = IO_DONE; 184 int err = IO_DONE;
200 while (err == IO_DONE || err == IO_RETRY) { 185 while (err == IO_DONE) {
201 size_t count, pos; const char *data; 186 size_t count, pos; const char *data;
202 err = buf_get(buf, &data, &count); 187 err = buf_get(buf, &data, &count);
203 pos = 0; 188 pos = 0;
@@ -219,9 +204,7 @@ int recvline(p_buf buf, luaL_Buffer *b)
219* Skips a given number of bytes from read buffer. No data is read from the 204* Skips a given number of bytes from read buffer. No data is read from the
220* transport layer 205* transport layer
221\*-------------------------------------------------------------------------*/ 206\*-------------------------------------------------------------------------*/
222static 207static void buf_skip(p_buf buf, size_t count) {
223void buf_skip(p_buf buf, size_t count)
224{
225 buf->first += count; 208 buf->first += count;
226 if (buf_isempty(buf)) 209 if (buf_isempty(buf))
227 buf->first = buf->last = 0; 210 buf->first = buf->last = 0;
@@ -231,15 +214,13 @@ void buf_skip(p_buf buf, size_t count)
231* Return any data available in buffer, or get more data from transport layer 214* Return any data available in buffer, or get more data from transport layer
232* if buffer is empty 215* if buffer is empty
233\*-------------------------------------------------------------------------*/ 216\*-------------------------------------------------------------------------*/
234static 217static int buf_get(p_buf buf, const char **data, size_t *count) {
235int buf_get(p_buf buf, const char **data, size_t *count)
236{
237 int err = IO_DONE; 218 int err = IO_DONE;
238 p_io io = buf->io; 219 p_io io = buf->io;
239 p_tm tm = buf->tm; 220 p_tm tm = buf->tm;
240 if (buf_isempty(buf)) { 221 if (buf_isempty(buf)) {
241 size_t got; 222 size_t got;
242 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm)); 223 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm);
243 buf->first = 0; 224 buf->first = 0;
244 buf->last = got; 225 buf->last = got;
245 } 226 }
@@ -247,4 +228,3 @@ int buf_get(p_buf buf, const char **data, size_t *count)
247 *data = buf->data + buf->first; 228 *data = buf->data + buf->first;
248 return err; 229 return err;
249} 230}
250
diff --git a/src/io.c b/src/io.c
index 612454b..30595c7 100644
--- a/src/io.c
+++ b/src/io.c
@@ -12,34 +12,34 @@
12/*-------------------------------------------------------------------------*\ 12/*-------------------------------------------------------------------------*\
13* Initializes C structure 13* Initializes C structure
14\*-------------------------------------------------------------------------*/ 14\*-------------------------------------------------------------------------*/
15void io_init(p_io io, p_send send, p_recv recv, void *ctx) 15void io_init(p_io io, p_send send, p_recv recv, p_geterr geterr, void *ctx) {
16{
17 io->send = send; 16 io->send = send;
18 io->recv = recv; 17 io->recv = recv;
18 io->geterr = geterr;
19 io->ctx = ctx; 19 io->ctx = ctx;
20} 20}
21 21
22/*-------------------------------------------------------------------------*\ 22/*-------------------------------------------------------------------------*\
23* Translate error codes to Lua 23* Translate error codes to Lua
24\*-------------------------------------------------------------------------*/ 24\*-------------------------------------------------------------------------*/
25const char *io_strerror(int code) 25const char *io_strerror(int code) {
26{
27 switch (code) { 26 switch (code) {
28 case IO_DONE: return NULL; 27 case IO_DONE: return NULL;
29 case IO_TIMEOUT: return "timeout";
30 case IO_RETRY: return "retry";
31 case IO_CLOSED: return "closed"; 28 case IO_CLOSED: return "closed";
32 case IO_REFUSED: return "refused"; 29 case IO_TIMEOUT: return "timeout";
30 case IO_CLIPPED: return "clipped";
33 default: return "unknown error"; 31 default: return "unknown error";
34 } 32 }
35} 33}
36 34
37/*-------------------------------------------------------------------------*\ 35/*-------------------------------------------------------------------------*\
38* Translate error codes to Lua 36* Push error message from code or from driver
39\*-------------------------------------------------------------------------*/ 37\*-------------------------------------------------------------------------*/
40void io_pusherror(lua_State *L, int code) 38void io_pusherror(lua_State *L, p_io io, int code)
41{ 39{
42 const char *err = io_strerror(code); 40 const char *err = NULL;
41 if (code < IO_USER) err = io_strerror(code);
42 else err = io->geterr(io->ctx, code);
43 if (err) lua_pushstring(L, err); 43 if (err) lua_pushstring(L, err);
44 else lua_pushnil(L); 44 else lua_pushnil(L);
45} 45}
diff --git a/src/io.h b/src/io.h
index 495bdc6..72602dd 100644
--- a/src/io.h
+++ b/src/io.h
@@ -17,14 +17,15 @@
17#include <stdio.h> 17#include <stdio.h>
18#include <lua.h> 18#include <lua.h>
19 19
20#include "timeout.h"
21
20/* IO error codes */ 22/* IO error codes */
21enum { 23enum {
22 IO_DONE, /* operation completed successfully */ 24 IO_DONE, /* operation completed successfully */
23 IO_RETRY, /* please try again */
24 IO_TIMEOUT, /* operation timed out */ 25 IO_TIMEOUT, /* operation timed out */
25 IO_CLOSED, /* the connection has been closed */ 26 IO_CLOSED, /* the connection has been closed */
26 IO_REFUSED, /* transfer has been refused */ 27 IO_CLIPPED, /* maxium bytes count reached */
27 IO_ERROR /* something else wrong... */ 28 IO_USER /* last element in enum is user custom error */
28}; 29};
29 30
30/* interface to send function */ 31/* interface to send function */
@@ -33,7 +34,13 @@ typedef int (*p_send) (
33 const char *data, /* pointer to buffer with data to send */ 34 const char *data, /* pointer to buffer with data to send */
34 size_t count, /* number of bytes to send from buffer */ 35 size_t count, /* number of bytes to send from buffer */
35 size_t *sent, /* number of bytes sent uppon return */ 36 size_t *sent, /* number of bytes sent uppon return */
36 int timeout /* number of miliseconds left for transmission */ 37 p_tm tm /* timeout control */
38);
39
40/* returns an error string */
41typedef const char *(*p_geterr) (
42 void *ctx, /* context needed by geterror */
43 int code /* error code */
37); 44);
38 45
39/* interface to recv function */ 46/* interface to recv function */
@@ -42,7 +49,7 @@ typedef int (*p_recv) (
42 char *data, /* pointer to buffer where data will be writen */ 49 char *data, /* pointer to buffer where data will be writen */
43 size_t count, /* number of bytes to receive into buffer */ 50 size_t count, /* number of bytes to receive into buffer */
44 size_t *got, /* number of bytes received uppon return */ 51 size_t *got, /* number of bytes received uppon return */
45 int timeout /* number of miliseconds left for transmission */ 52 p_tm tm /* timeout control */
46); 53);
47 54
48/* IO driver definition */ 55/* IO driver definition */
@@ -50,11 +57,12 @@ typedef struct t_io_ {
50 void *ctx; /* context needed by send/recv */ 57 void *ctx; /* context needed by send/recv */
51 p_send send; /* send function pointer */ 58 p_send send; /* send function pointer */
52 p_recv recv; /* receive function pointer */ 59 p_recv recv; /* receive function pointer */
60 p_geterr geterr; /* receive function pointer */
53} t_io; 61} t_io;
54typedef t_io *p_io; 62typedef t_io *p_io;
55 63
56const char *io_strerror(int code); 64const char *io_strerror(int code);
57void io_pusherror(lua_State *L, int code); 65void io_pusherror(lua_State *L, p_io io, int code);
58void io_init(p_io io, p_send send, p_recv recv, void *ctx); 66void io_init(p_io io, p_send send, p_recv recv, p_geterr geterr, void *ctx);
59 67
60#endif /* IO_H */ 68#endif /* IO_H */
diff --git a/src/select.c b/src/select.c
index 49730d1..3c01b06 100644
--- a/src/select.c
+++ b/src/select.c
@@ -10,6 +10,7 @@
10#include <lauxlib.h> 10#include <lauxlib.h>
11 11
12#include "socket.h" 12#include "socket.h"
13#include "timeout.h"
13#include "select.h" 14#include "select.h"
14 15
15/*=========================================================================*\ 16/*=========================================================================*\
@@ -48,19 +49,21 @@ int select_open(lua_State *L) {
48* Waits for a set of sockets until a condition is met or timeout. 49* Waits for a set of sockets until a condition is met or timeout.
49\*-------------------------------------------------------------------------*/ 50\*-------------------------------------------------------------------------*/
50static int global_select(lua_State *L) { 51static int global_select(lua_State *L) {
51 int timeout, rtab, wtab, itab, max_fd, ret, ndirty; 52 int rtab, wtab, itab, max_fd, ret, ndirty;
52 fd_set rset, wset; 53 fd_set rset, wset;
54 t_tm tm;
55 double t = luaL_optnumber(L, 3, -1);
53 FD_ZERO(&rset); FD_ZERO(&wset); 56 FD_ZERO(&rset); FD_ZERO(&wset);
54 lua_settop(L, 3); 57 lua_settop(L, 3);
55 timeout = lua_isnil(L, 3) ? -1 : (int)(luaL_checknumber(L, 3) * 1000);
56 lua_newtable(L); itab = lua_gettop(L); 58 lua_newtable(L); itab = lua_gettop(L);
57 lua_newtable(L); rtab = lua_gettop(L); 59 lua_newtable(L); rtab = lua_gettop(L);
58 lua_newtable(L); wtab = lua_gettop(L); 60 lua_newtable(L); wtab = lua_gettop(L);
59 max_fd = collect_fd(L, 1, -1, itab, &rset); 61 max_fd = collect_fd(L, 1, -1, itab, &rset);
60 ndirty = check_dirty(L, 1, rtab, &rset); 62 ndirty = check_dirty(L, 1, rtab, &rset);
61 timeout = ndirty > 0? 0: timeout; 63 t = ndirty > 0? 0.0: t;
64 tm_init(&tm, t, -1);
62 max_fd = collect_fd(L, 2, max_fd, itab, &wset); 65 max_fd = collect_fd(L, 2, max_fd, itab, &wset);
63 ret = sock_select(max_fd+1, &rset, &wset, NULL, timeout); 66 ret = sock_select(max_fd+1, &rset, &wset, NULL, &tm);
64 if (ret > 0 || (ret == 0 && ndirty > 0)) { 67 if (ret > 0 || (ret == 0 && ndirty > 0)) {
65 return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); 68 return_fd(L, &rset, max_fd+1, itab, rtab, ndirty);
66 return_fd(L, &wset, max_fd+1, itab, wtab, 0); 69 return_fd(L, &wset, max_fd+1, itab, wtab, 0);
diff --git a/src/socket.h b/src/socket.h
index 5da1ccc..787b7a5 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -41,17 +41,15 @@ int sock_open(void);
41int sock_close(void); 41int sock_close(void);
42void sock_destroy(p_sock ps); 42void sock_destroy(p_sock ps);
43void sock_shutdown(p_sock ps, int how); 43void sock_shutdown(p_sock ps, int how);
44int sock_send(p_sock ps, const char *data, size_t count, 44int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm);
45 size_t *sent, int timeout); 45int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm);
46int sock_recv(p_sock ps, char *data, size_t count,
47 size_t *got, int timeout);
48int sock_sendto(p_sock ps, const char *data, size_t count, 46int sock_sendto(p_sock ps, const char *data, size_t count,
49 size_t *sent, SA *addr, socklen_t addr_len, int timeout); 47 size_t *sent, SA *addr, socklen_t addr_len, p_tm tm);
50int sock_recvfrom(p_sock ps, char *data, size_t count, 48int sock_recvfrom(p_sock ps, char *data, size_t count,
51 size_t *got, SA *addr, socklen_t *addr_len, int timeout); 49 size_t *got, SA *addr, socklen_t *addr_len, p_tm tm);
52void sock_setnonblocking(p_sock ps); 50void sock_setnonblocking(p_sock ps);
53void sock_setblocking(p_sock ps); 51void sock_setblocking(p_sock ps);
54int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout); 52int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm);
55 53
56const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm); 54const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm);
57const char *sock_create(p_sock ps, int domain, int type, int protocol); 55const char *sock_create(p_sock ps, int domain, int type, int protocol);
@@ -60,6 +58,8 @@ const char *sock_listen(p_sock ps, int backlog);
60const char *sock_accept(p_sock ps, p_sock pa, SA *addr, 58const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
61 socklen_t *addr_len, p_tm tm); 59 socklen_t *addr_len, p_tm tm);
62 60
61const char *sock_geterr(p_sock ps, int code);
63const char *sock_hoststrerror(void); 62const char *sock_hoststrerror(void);
63const char *sock_strerror(void);
64 64
65#endif /* SOCK_H */ 65#endif /* SOCK_H */
diff --git a/src/tcp.c b/src/tcp.c
index 6c58494..8ab7d62 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -163,7 +163,8 @@ static int meth_accept(lua_State *L)
163 /* initialize structure fields */ 163 /* initialize structure fields */
164 sock_setnonblocking(&sock); 164 sock_setnonblocking(&sock);
165 clnt->sock = sock; 165 clnt->sock = sock;
166 io_init(&clnt->io, (p_send)sock_send, (p_recv)sock_recv, &clnt->sock); 166 io_init(&clnt->io, (p_send) sock_send, (p_recv) sock_recv,
167 (p_geterr) sock_geterr, &clnt->sock);
167 tm_init(&clnt->tm, -1, -1); 168 tm_init(&clnt->tm, -1, -1);
168 buf_init(&clnt->buf, &clnt->io, &clnt->tm); 169 buf_init(&clnt->buf, &clnt->io, &clnt->tm);
169 return 1; 170 return 1;
@@ -313,7 +314,8 @@ static int global_create(lua_State *L)
313 /* initialize remaining structure fields */ 314 /* initialize remaining structure fields */
314 sock_setnonblocking(&sock); 315 sock_setnonblocking(&sock);
315 tcp->sock = sock; 316 tcp->sock = sock;
316 io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv, &tcp->sock); 317 io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv,
318 (p_geterr) sock_geterr, &tcp->sock);
317 tm_init(&tcp->tm, -1, -1); 319 tm_init(&tcp->tm, -1, -1);
318 buf_init(&tcp->buf, &tcp->io, &tcp->tm); 320 buf_init(&tcp->buf, &tcp->io, &tcp->tm);
319 return 1; 321 return 1;
diff --git a/src/timeout.c b/src/timeout.c
index dcc2105..74ba968 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -46,8 +46,7 @@ static luaL_reg func[] = {
46/*-------------------------------------------------------------------------*\ 46/*-------------------------------------------------------------------------*\
47* Initialize structure 47* Initialize structure
48\*-------------------------------------------------------------------------*/ 48\*-------------------------------------------------------------------------*/
49void tm_init(p_tm tm, int block, int total) 49void tm_init(p_tm tm, double block, double total) {
50{
51 tm->block = block; 50 tm->block = block;
52 tm->total = total; 51 tm->total = total;
53} 52}
@@ -60,18 +59,17 @@ void tm_init(p_tm tm, int block, int total)
60* Returns 59* Returns
61* the number of ms left or -1 if there is no time limit 60* the number of ms left or -1 if there is no time limit
62\*-------------------------------------------------------------------------*/ 61\*-------------------------------------------------------------------------*/
63int tm_get(p_tm tm) 62double tm_get(p_tm tm) {
64{ 63 if (tm->block < 0.0 && tm->total < 0.0) {
65 if (tm->block < 0 && tm->total < 0) {
66 return -1; 64 return -1;
67 } else if (tm->block < 0) { 65 } else if (tm->block < 0.0) {
68 int t = tm->total - tm_gettime() + tm->start; 66 double t = tm->total - tm_gettime() + tm->start;
69 return MAX(t, 0); 67 return MAX(t, 0.0);
70 } else if (tm->total < 0) { 68 } else if (tm->total < 0.0) {
71 return tm->block; 69 return tm->block;
72 } else { 70 } else {
73 int t = tm->total - tm_gettime() + tm->start; 71 double t = tm->total - tm_gettime() + tm->start;
74 return MIN(tm->block, MAX(t, 0)); 72 return MIN(tm->block, MAX(t, 0.0));
75 } 73 }
76} 74}
77 75
@@ -82,8 +80,7 @@ int tm_get(p_tm tm)
82* Returns 80* Returns
83* start field of structure 81* start field of structure
84\*-------------------------------------------------------------------------*/ 82\*-------------------------------------------------------------------------*/
85int tm_getstart(p_tm tm) 83double tm_getstart(p_tm tm) {
86{
87 return tm->start; 84 return tm->start;
88} 85}
89 86
@@ -95,19 +92,18 @@ int tm_getstart(p_tm tm)
95* Returns 92* Returns
96* the number of ms left or -1 if there is no time limit 93* the number of ms left or -1 if there is no time limit
97\*-------------------------------------------------------------------------*/ 94\*-------------------------------------------------------------------------*/
98int tm_getretry(p_tm tm) 95double tm_getretry(p_tm tm) {
99{ 96 if (tm->block < 0.0 && tm->total < 0.0) {
100 if (tm->block < 0 && tm->total < 0) {
101 return -1; 97 return -1;
102 } else if (tm->block < 0) { 98 } else if (tm->block < 0.0) {
103 int t = tm->total - tm_gettime() + tm->start; 99 double t = tm->total - tm_gettime() + tm->start;
104 return MAX(t, 0); 100 return MAX(t, 0.0);
105 } else if (tm->total < 0) { 101 } else if (tm->total < 0.0) {
106 int t = tm->block - tm_gettime() + tm->start; 102 double t = tm->block - tm_gettime() + tm->start;
107 return MAX(t, 0); 103 return MAX(t, 0.0);
108 } else { 104 } else {
109 int t = tm->total - tm_gettime() + tm->start; 105 double t = tm->total - tm_gettime() + tm->start;
110 return MIN(tm->block, MAX(t, 0)); 106 return MIN(tm->block, MAX(t, 0.0));
111 } 107 }
112} 108}
113 109
@@ -116,8 +112,7 @@ int tm_getretry(p_tm tm)
116* Input 112* Input
117* tm: timeout control structure 113* tm: timeout control structure
118\*-------------------------------------------------------------------------*/ 114\*-------------------------------------------------------------------------*/
119p_tm tm_markstart(p_tm tm) 115p_tm tm_markstart(p_tm tm) {
120{
121 tm->start = tm_gettime(); 116 tm->start = tm_gettime();
122 return tm; 117 return tm;
123} 118}
@@ -128,24 +123,23 @@ p_tm tm_markstart(p_tm tm)
128* time in ms. 123* time in ms.
129\*-------------------------------------------------------------------------*/ 124\*-------------------------------------------------------------------------*/
130#ifdef _WIN32 125#ifdef _WIN32
131int tm_gettime(void) 126double tm_gettime(void) {
132{ 127 FILETIME ft;
133 return GetTickCount(); 128 GetSystemTimeAsFileTime(&ft);
129 return ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
134} 130}
135#else 131#else
136int tm_gettime(void) 132double tm_gettime(void) {
137{
138 struct timeval v; 133 struct timeval v;
139 gettimeofday(&v, (struct timezone *) NULL); 134 gettimeofday(&v, (struct timezone *) NULL);
140 return v.tv_sec * 1000 + v.tv_usec/1000; 135 return v.tv_sec + v.tv_usec/1.0e6;
141} 136}
142#endif 137#endif
143 138
144/*-------------------------------------------------------------------------*\ 139/*-------------------------------------------------------------------------*\
145* Initializes module 140* Initializes module
146\*-------------------------------------------------------------------------*/ 141\*-------------------------------------------------------------------------*/
147int tm_open(lua_State *L) 142int tm_open(lua_State *L) {
148{
149 luaL_openlib(L, NULL, func, 0); 143 luaL_openlib(L, NULL, func, 0);
150 return 0; 144 return 0;
151} 145}
@@ -156,16 +150,15 @@ int tm_open(lua_State *L)
156* time: time out value in seconds 150* time: time out value in seconds
157* mode: "b" for block timeout, "t" for total timeout. (default: b) 151* mode: "b" for block timeout, "t" for total timeout. (default: b)
158\*-------------------------------------------------------------------------*/ 152\*-------------------------------------------------------------------------*/
159int tm_meth_settimeout(lua_State *L, p_tm tm) 153int tm_meth_settimeout(lua_State *L, p_tm tm) {
160{ 154 double t = luaL_optnumber(L, 2, -1);
161 int ms = lua_isnil(L, 2) ? -1 : (int) (luaL_checknumber(L, 2)*1000.0);
162 const char *mode = luaL_optstring(L, 3, "b"); 155 const char *mode = luaL_optstring(L, 3, "b");
163 switch (*mode) { 156 switch (*mode) {
164 case 'b': 157 case 'b':
165 tm->block = ms; 158 tm->block = t;
166 break; 159 break;
167 case 'r': case 't': 160 case 'r': case 't':
168 tm->total = ms; 161 tm->total = t;
169 break; 162 break;
170 default: 163 default:
171 luaL_argcheck(L, 0, 3, "invalid timeout mode"); 164 luaL_argcheck(L, 0, 3, "invalid timeout mode");
@@ -183,7 +176,7 @@ int tm_meth_settimeout(lua_State *L, p_tm tm)
183\*-------------------------------------------------------------------------*/ 176\*-------------------------------------------------------------------------*/
184static int tm_lua_gettime(lua_State *L) 177static int tm_lua_gettime(lua_State *L)
185{ 178{
186 lua_pushnumber(L, tm_gettime()/1000.0); 179 lua_pushnumber(L, tm_gettime());
187 return 1; 180 return 1;
188} 181}
189 182
diff --git a/src/timeout.h b/src/timeout.h
index 6b105c3..817922f 100644
--- a/src/timeout.h
+++ b/src/timeout.h
@@ -10,19 +10,19 @@
10 10
11/* timeout control structure */ 11/* timeout control structure */
12typedef struct t_tm_ { 12typedef struct t_tm_ {
13 int total; /* total number of miliseconds for operation */ 13 double total; /* total number of miliseconds for operation */
14 int block; /* maximum time for blocking calls */ 14 double block; /* maximum time for blocking calls */
15 int start; /* time of start of operation */ 15 double start; /* time of start of operation */
16} t_tm; 16} t_tm;
17typedef t_tm *p_tm; 17typedef t_tm *p_tm;
18 18
19int tm_open(lua_State *L); 19int tm_open(lua_State *L);
20void tm_init(p_tm tm, int block, int total); 20void tm_init(p_tm tm, double block, double total);
21int tm_get(p_tm tm); 21double tm_get(p_tm tm);
22int tm_getretry(p_tm tm); 22double tm_getretry(p_tm tm);
23p_tm tm_markstart(p_tm tm); 23p_tm tm_markstart(p_tm tm);
24int tm_getstart(p_tm tm); 24double tm_getstart(p_tm tm);
25int tm_gettime(void); 25double tm_gettime(void);
26int tm_meth_settimeout(lua_State *L, p_tm tm); 26int tm_meth_settimeout(lua_State *L, p_tm tm);
27 27
28#endif /* TM_H */ 28#endif /* TM_H */
diff --git a/src/udp.c b/src/udp.c
index d20d61b..a71be73 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -41,25 +41,26 @@ static int meth_settimeout(lua_State *L);
41static int meth_getfd(lua_State *L); 41static int meth_getfd(lua_State *L);
42static int meth_setfd(lua_State *L); 42static int meth_setfd(lua_State *L);
43static int meth_dirty(lua_State *L); 43static int meth_dirty(lua_State *L);
44static void pusherror(lua_State *L, int code);
44 45
45/* udp object methods */ 46/* udp object methods */
46static luaL_reg udp[] = { 47static luaL_reg udp[] = {
47 {"setpeername", meth_setpeername},
48 {"setsockname", meth_setsockname},
49 {"getsockname", meth_getsockname},
50 {"getpeername", meth_getpeername},
51 {"send", meth_send},
52 {"sendto", meth_sendto},
53 {"receive", meth_receive},
54 {"receivefrom", meth_receivefrom},
55 {"settimeout", meth_settimeout},
56 {"close", meth_close},
57 {"setoption", meth_setoption},
58 {"__gc", meth_close}, 48 {"__gc", meth_close},
59 {"__tostring", aux_tostring}, 49 {"__tostring", aux_tostring},
50 {"close", meth_close},
51 {"dirty", meth_dirty},
60 {"getfd", meth_getfd}, 52 {"getfd", meth_getfd},
53 {"getpeername", meth_getpeername},
54 {"getsockname", meth_getsockname},
55 {"receive", meth_receive},
56 {"receivefrom", meth_receivefrom},
57 {"send", meth_send},
58 {"sendto", meth_sendto},
61 {"setfd", meth_setfd}, 59 {"setfd", meth_setfd},
62 {"dirty", meth_dirty}, 60 {"setoption", meth_setoption},
61 {"setpeername", meth_setpeername},
62 {"setsockname", meth_setsockname},
63 {"settimeout", meth_settimeout},
63 {NULL, NULL} 64 {NULL, NULL}
64}; 65};
65 66
@@ -99,35 +100,43 @@ int udp_open(lua_State *L)
99 return 0; 100 return 0;
100} 101}
101 102
103
102/*=========================================================================*\ 104/*=========================================================================*\
103* Lua methods 105* Lua methods
104\*=========================================================================*/ 106\*=========================================================================*/
105/*-------------------------------------------------------------------------*\ 107/*-------------------------------------------------------------------------*\
108* Pushes the error message
109\*-------------------------------------------------------------------------*/
110void pusherror(lua_State *L, int code) {
111 const char *err = code != IO_USER? io_strerror(code): "refused";
112 err = err? err: sock_strerror();
113 if (err) lua_pushstring(L, err);
114 else lua_pushnil(L);
115}
116
117/*-------------------------------------------------------------------------*\
106* Send data through connected udp socket 118* Send data through connected udp socket
107\*-------------------------------------------------------------------------*/ 119\*-------------------------------------------------------------------------*/
108static int meth_send(lua_State *L) 120static int meth_send(lua_State *L) {
109{
110 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1); 121 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
111 p_tm tm = &udp->tm; 122 p_tm tm = &udp->tm;
112 size_t count, sent = 0; 123 size_t count, sent = 0;
113 int err; 124 int err;
114 const char *data = luaL_checklstring(L, 2, &count); 125 const char *data = luaL_checklstring(L, 2, &count);
115 tm_markstart(tm); 126 tm_markstart(tm);
116 do err = sock_send(&udp->sock, data, count, &sent, tm_getretry(tm)); 127 err = sock_send(&udp->sock, data, count, &sent, tm);
117 while (err == IO_RETRY);
118 if (err == IO_DONE) lua_pushnumber(L, sent); 128 if (err == IO_DONE) lua_pushnumber(L, sent);
119 else lua_pushnil(L); 129 else lua_pushnil(L);
120 /* a 'closed' error on an unconnected means the target address was not 130 /* a 'closed' error on an unconnected means the target address was not
121 * accepted by the transport layer */ 131 * accepted by the transport layer */
122 io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err); 132 pusherror(L, err == IO_CLOSED ? IO_USER : err);
123 return 2; 133 return 2;
124} 134}
125 135
126/*-------------------------------------------------------------------------*\ 136/*-------------------------------------------------------------------------*\
127* Send data through unconnected udp socket 137* Send data through unconnected udp socket
128\*-------------------------------------------------------------------------*/ 138\*-------------------------------------------------------------------------*/
129static int meth_sendto(lua_State *L) 139static int meth_sendto(lua_State *L) {
130{
131 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 140 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
132 size_t count, sent = 0; 141 size_t count, sent = 0;
133 const char *data = luaL_checklstring(L, 2, &count); 142 const char *data = luaL_checklstring(L, 2, &count);
@@ -142,22 +151,20 @@ static int meth_sendto(lua_State *L)
142 addr.sin_family = AF_INET; 151 addr.sin_family = AF_INET;
143 addr.sin_port = htons(port); 152 addr.sin_port = htons(port);
144 tm_markstart(tm); 153 tm_markstart(tm);
145 do err = sock_sendto(&udp->sock, data, count, &sent, 154 err = sock_sendto(&udp->sock, data, count, &sent,
146 (SA *) &addr, sizeof(addr), tm_get(tm)); 155 (SA *) &addr, sizeof(addr), tm);
147 while (err == IO_RETRY);
148 if (err == IO_DONE) lua_pushnumber(L, sent); 156 if (err == IO_DONE) lua_pushnumber(L, sent);
149 else lua_pushnil(L); 157 else lua_pushnil(L);
150 /* a 'closed' error on an unconnected means the target address was not 158 /* a 'closed' error on an unconnected means the target address was not
151 * accepted by the transport layer */ 159 * accepted by the transport layer */
152 io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err); 160 pusherror(L, err == IO_CLOSED ? IO_USER : err);
153 return 2; 161 return 2;
154} 162}
155 163
156/*-------------------------------------------------------------------------*\ 164/*-------------------------------------------------------------------------*\
157* Receives data from a UDP socket 165* Receives data from a UDP socket
158\*-------------------------------------------------------------------------*/ 166\*-------------------------------------------------------------------------*/
159static int meth_receive(lua_State *L) 167static int meth_receive(lua_State *L) {
160{
161 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 168 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
162 char buffer[UDP_DATAGRAMSIZE]; 169 char buffer[UDP_DATAGRAMSIZE];
163 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 170 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
@@ -165,19 +172,17 @@ static int meth_receive(lua_State *L)
165 p_tm tm = &udp->tm; 172 p_tm tm = &udp->tm;
166 count = MIN(count, sizeof(buffer)); 173 count = MIN(count, sizeof(buffer));
167 tm_markstart(tm); 174 tm_markstart(tm);
168 do err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm)); 175 err = sock_recv(&udp->sock, buffer, count, &got, tm);
169 while (err == IO_RETRY);
170 if (err == IO_DONE) lua_pushlstring(L, buffer, got); 176 if (err == IO_DONE) lua_pushlstring(L, buffer, got);
171 else lua_pushnil(L); 177 else lua_pushnil(L);
172 io_pusherror(L, err); 178 pusherror(L, err);
173 return 2; 179 return 2;
174} 180}
175 181
176/*-------------------------------------------------------------------------*\ 182/*-------------------------------------------------------------------------*\
177* Receives data and sender from a UDP socket 183* Receives data and sender from a UDP socket
178\*-------------------------------------------------------------------------*/ 184\*-------------------------------------------------------------------------*/
179static int meth_receivefrom(lua_State *L) 185static int meth_receivefrom(lua_State *L) {
180{
181 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 186 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
182 struct sockaddr_in addr; 187 struct sockaddr_in addr;
183 socklen_t addr_len = sizeof(addr); 188 socklen_t addr_len = sizeof(addr);
@@ -187,9 +192,8 @@ static int meth_receivefrom(lua_State *L)
187 p_tm tm = &udp->tm; 192 p_tm tm = &udp->tm;
188 tm_markstart(tm); 193 tm_markstart(tm);
189 count = MIN(count, sizeof(buffer)); 194 count = MIN(count, sizeof(buffer));
190 do err = sock_recvfrom(&udp->sock, buffer, count, &got, 195 err = sock_recvfrom(&udp->sock, buffer, count, &got,
191 (SA *) &addr, &addr_len, tm_get(tm)); 196 (SA *) &addr, &addr_len, tm);
192 while (err == IO_RETRY);
193 if (err == IO_DONE) { 197 if (err == IO_DONE) {
194 lua_pushlstring(L, buffer, got); 198 lua_pushlstring(L, buffer, got);
195 lua_pushstring(L, inet_ntoa(addr.sin_addr)); 199 lua_pushstring(L, inet_ntoa(addr.sin_addr));
@@ -197,7 +201,7 @@ static int meth_receivefrom(lua_State *L)
197 return 3; 201 return 3;
198 } else { 202 } else {
199 lua_pushnil(L); 203 lua_pushnil(L);
200 io_pusherror(L, err); 204 pusherror(L, err);
201 return 2; 205 return 2;
202 } 206 }
203} 207}
@@ -205,23 +209,20 @@ static int meth_receivefrom(lua_State *L)
205/*-------------------------------------------------------------------------*\ 209/*-------------------------------------------------------------------------*\
206* Select support methods 210* Select support methods
207\*-------------------------------------------------------------------------*/ 211\*-------------------------------------------------------------------------*/
208static int meth_getfd(lua_State *L) 212static int meth_getfd(lua_State *L) {
209{
210 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 213 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
211 lua_pushnumber(L, (int) udp->sock); 214 lua_pushnumber(L, (int) udp->sock);
212 return 1; 215 return 1;
213} 216}
214 217
215/* this is very dangerous, but can be handy for those that are brave enough */ 218/* this is very dangerous, but can be handy for those that are brave enough */
216static int meth_setfd(lua_State *L) 219static int meth_setfd(lua_State *L) {
217{
218 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 220 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
219 udp->sock = (t_sock) luaL_checknumber(L, 2); 221 udp->sock = (t_sock) luaL_checknumber(L, 2);
220 return 0; 222 return 0;
221} 223}
222 224
223static int meth_dirty(lua_State *L) 225static int meth_dirty(lua_State *L) {
224{
225 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 226 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
226 (void) udp; 227 (void) udp;
227 lua_pushboolean(L, 0); 228 lua_pushboolean(L, 0);
@@ -231,14 +232,12 @@ static int meth_dirty(lua_State *L)
231/*-------------------------------------------------------------------------*\ 232/*-------------------------------------------------------------------------*\
232* Just call inet methods 233* Just call inet methods
233\*-------------------------------------------------------------------------*/ 234\*-------------------------------------------------------------------------*/
234static int meth_getpeername(lua_State *L) 235static int meth_getpeername(lua_State *L) {
235{
236 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1); 236 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
237 return inet_meth_getpeername(L, &udp->sock); 237 return inet_meth_getpeername(L, &udp->sock);
238} 238}
239 239
240static int meth_getsockname(lua_State *L) 240static int meth_getsockname(lua_State *L) {
241{
242 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 241 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
243 return inet_meth_getsockname(L, &udp->sock); 242 return inet_meth_getsockname(L, &udp->sock);
244} 243}
@@ -246,8 +245,7 @@ static int meth_getsockname(lua_State *L)
246/*-------------------------------------------------------------------------*\ 245/*-------------------------------------------------------------------------*\
247* Just call option handler 246* Just call option handler
248\*-------------------------------------------------------------------------*/ 247\*-------------------------------------------------------------------------*/
249static int meth_setoption(lua_State *L) 248static int meth_setoption(lua_State *L) {
250{
251 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 249 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
252 return opt_meth_setoption(L, opt, &udp->sock); 250 return opt_meth_setoption(L, opt, &udp->sock);
253} 251}
@@ -255,8 +253,7 @@ static int meth_setoption(lua_State *L)
255/*-------------------------------------------------------------------------*\ 253/*-------------------------------------------------------------------------*\
256* Just call tm methods 254* Just call tm methods
257\*-------------------------------------------------------------------------*/ 255\*-------------------------------------------------------------------------*/
258static int meth_settimeout(lua_State *L) 256static int meth_settimeout(lua_State *L) {
259{
260 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 257 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
261 return tm_meth_settimeout(L, &udp->tm); 258 return tm_meth_settimeout(L, &udp->tm);
262} 259}
@@ -264,8 +261,7 @@ static int meth_settimeout(lua_State *L)
264/*-------------------------------------------------------------------------*\ 261/*-------------------------------------------------------------------------*\
265* Turns a master udp object into a client object. 262* Turns a master udp object into a client object.
266\*-------------------------------------------------------------------------*/ 263\*-------------------------------------------------------------------------*/
267static int meth_setpeername(lua_State *L) 264static int meth_setpeername(lua_State *L) {
268{
269 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 265 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
270 p_tm tm = &udp->tm; 266 p_tm tm = &udp->tm;
271 const char *address = luaL_checkstring(L, 2); 267 const char *address = luaL_checkstring(L, 2);
@@ -289,8 +285,7 @@ static int meth_setpeername(lua_State *L)
289/*-------------------------------------------------------------------------*\ 285/*-------------------------------------------------------------------------*\
290* Closes socket used by object 286* Closes socket used by object
291\*-------------------------------------------------------------------------*/ 287\*-------------------------------------------------------------------------*/
292static int meth_close(lua_State *L) 288static int meth_close(lua_State *L) {
293{
294 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 289 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
295 sock_destroy(&udp->sock); 290 sock_destroy(&udp->sock);
296 return 0; 291 return 0;
@@ -299,8 +294,7 @@ static int meth_close(lua_State *L)
299/*-------------------------------------------------------------------------*\ 294/*-------------------------------------------------------------------------*\
300* Turns a master object into a server object 295* Turns a master object into a server object
301\*-------------------------------------------------------------------------*/ 296\*-------------------------------------------------------------------------*/
302static int meth_setsockname(lua_State *L) 297static int meth_setsockname(lua_State *L) {
303{
304 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 298 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
305 const char *address = luaL_checkstring(L, 2); 299 const char *address = luaL_checkstring(L, 2);
306 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 300 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
@@ -320,8 +314,7 @@ static int meth_setsockname(lua_State *L)
320/*-------------------------------------------------------------------------*\ 314/*-------------------------------------------------------------------------*\
321* Creates a master udp object 315* Creates a master udp object
322\*-------------------------------------------------------------------------*/ 316\*-------------------------------------------------------------------------*/
323static int global_create(lua_State *L) 317static int global_create(lua_State *L) {
324{
325 t_sock sock; 318 t_sock sock;
326 const char *err = inet_trycreate(&sock, SOCK_DGRAM); 319 const char *err = inet_trycreate(&sock, SOCK_DGRAM);
327 /* try to allocate a system socket */ 320 /* try to allocate a system socket */
diff --git a/src/usocket.c b/src/usocket.c
index cf0458d..12a13a5 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -20,17 +20,10 @@
20 20
21#include "socket.h" 21#include "socket.h"
22 22
23static const char *sock_createstrerror(int err);
24static const char *sock_bindstrerror(int err);
25static const char *sock_connectstrerror(int err);
26static const char *sock_acceptstrerror(int err);
27static const char *sock_listenstrerror(int err);
28
29/*-------------------------------------------------------------------------*\ 23/*-------------------------------------------------------------------------*\
30* Initializes module 24* Initializes module
31\*-------------------------------------------------------------------------*/ 25\*-------------------------------------------------------------------------*/
32int sock_open(void) 26int sock_open(void) {
33{
34#if DOESNT_COMPILE_TRY_THIS 27#if DOESNT_COMPILE_TRY_THIS
35 struct sigaction ignore; 28 struct sigaction ignore;
36 memset(&ignore, 0, sizeof(ignore)); 29 memset(&ignore, 0, sizeof(ignore));
@@ -45,16 +38,14 @@ int sock_open(void)
45/*-------------------------------------------------------------------------*\ 38/*-------------------------------------------------------------------------*\
46* Close module 39* Close module
47\*-------------------------------------------------------------------------*/ 40\*-------------------------------------------------------------------------*/
48int sock_close(void) 41int sock_close(void) {
49{
50 return 1; 42 return 1;
51} 43}
52 44
53/*-------------------------------------------------------------------------*\ 45/*-------------------------------------------------------------------------*\
54* Close and inutilize socket 46* Close and inutilize socket
55\*-------------------------------------------------------------------------*/ 47\*-------------------------------------------------------------------------*/
56void sock_destroy(p_sock ps) 48void sock_destroy(p_sock ps) {
57{
58 if (*ps != SOCK_INVALID) { 49 if (*ps != SOCK_INVALID) {
59 sock_setblocking(ps); 50 sock_setblocking(ps);
60 close(*ps); 51 close(*ps);
@@ -63,23 +54,26 @@ void sock_destroy(p_sock ps)
63} 54}
64 55
65/*-------------------------------------------------------------------------*\ 56/*-------------------------------------------------------------------------*\
66* Select with int timeout in ms 57* Select with timeout control
67\*-------------------------------------------------------------------------*/ 58\*-------------------------------------------------------------------------*/
68int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout) 59int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm) {
69{ 60 int ret;
70 struct timeval tv; 61 do {
71 tv.tv_sec = timeout / 1000; 62 struct timeval tv;
72 tv.tv_usec = (timeout % 1000) * 1000; 63 double t = tm_getretry(tm);
73 return select(n, rfds, wfds, efds, timeout >= 0? &tv: NULL); 64 tv.tv_sec = (int) t;
65 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
66 ret = select(n, rfds, wfds, efds, t >= 0.0? &tv: NULL);
67 } while (ret < 0 && errno == EINTR);
68 return ret;
74} 69}
75 70
76/*-------------------------------------------------------------------------*\ 71/*-------------------------------------------------------------------------*\
77* Creates and sets up a socket 72* Creates and sets up a socket
78\*-------------------------------------------------------------------------*/ 73\*-------------------------------------------------------------------------*/
79const char *sock_create(p_sock ps, int domain, int type, int protocol) 74const char *sock_create(p_sock ps, int domain, int type, int protocol) {
80{
81 t_sock sock = socket(domain, type, protocol); 75 t_sock sock = socket(domain, type, protocol);
82 if (sock == SOCK_INVALID) return sock_createstrerror(errno); 76 if (sock == SOCK_INVALID) return sock_strerror();
83 *ps = sock; 77 *ps = sock;
84 return NULL; 78 return NULL;
85} 79}
@@ -87,50 +81,49 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol)
87/*-------------------------------------------------------------------------*\ 81/*-------------------------------------------------------------------------*\
88* Connects or returns error message 82* Connects or returns error message
89\*-------------------------------------------------------------------------*/ 83\*-------------------------------------------------------------------------*/
90const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) 84const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) {
91{
92 t_sock sock = *ps; 85 t_sock sock = *ps;
93 int err; 86 int err;
94 /* don't call on closed socket */ 87 /* don't call on closed socket */
95 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); 88 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED);
96 /* ask system to connect */ 89 /* ask system to connect */
97 do err = connect(sock, addr, addr_len); 90 do err = connect(sock, addr, addr_len);
98 while (err < 0 && errno == EINTR); 91 while (err < 0 && errno == EINTR);
99 /* if no error, we're done */ 92 /* if no error, we're done */
100 if (err == 0) return NULL; 93 if (err == 0) return NULL;
101 /* make sure the system is trying to connect */ 94 /* make sure the system is trying to connect */
102 if (errno != EINPROGRESS) return sock_connectstrerror(errno); 95 if (errno != EINPROGRESS) return sock_strerror();
96 /* optimize for timeout = 0 */
97 if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT);
103 /* wait for a timeout or for the system's answer */ 98 /* wait for a timeout or for the system's answer */
104 for ( ;; ) { 99 for ( ;; ) {
105 fd_set rfds, wfds, efds; 100 fd_set rfds, wfds;
106 FD_ZERO(&rfds); FD_SET(sock, &rfds); 101 FD_ZERO(&rfds); FD_SET(sock, &rfds);
107 FD_ZERO(&wfds); FD_SET(sock, &wfds); 102 FD_ZERO(&wfds); FD_SET(sock, &wfds);
108 FD_ZERO(&efds); FD_SET(sock, &efds);
109 /* we run select to avoid busy waiting */ 103 /* we run select to avoid busy waiting */
110 do err = sock_select(sock+1, &rfds, &wfds, &efds, tm_getretry(tm)); 104 err = sock_select(sock+1, &rfds, &wfds, NULL, tm);
111 while (err < 0 && errno == EINTR); 105 /* if there was an event, check what happened */
112 /* if selects readable, try reading */
113 if (err > 0) { 106 if (err > 0) {
114 char dummy; 107 char dummy;
115 /* recv will set errno to the value a blocking connect would set */ 108 /* recv will set errno to the value a blocking connect would set */
116 if (recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN) 109 if (err > 1 && FD_ISSET(sock, &rfds) &&
117 return sock_connectstrerror(errno); 110 recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN)
111 return sock_strerror();
118 else 112 else
119 return NULL; 113 return NULL;
120 /* if no event happened, there was a timeout */ 114 /* if no event happened, there was a timeout */
121 } else return io_strerror(IO_TIMEOUT); 115 } else if (err == 0) return io_strerror(IO_TIMEOUT);
122 } 116 }
123 return io_strerror(IO_TIMEOUT); /* can't get here */ 117 return sock_strerror();
124} 118}
125 119
126/*-------------------------------------------------------------------------*\ 120/*-------------------------------------------------------------------------*\
127* Binds or returns error message 121* Binds or returns error message
128\*-------------------------------------------------------------------------*/ 122\*-------------------------------------------------------------------------*/
129const 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) {
130{
131 const char *err = NULL; 124 const char *err = NULL;
132 sock_setblocking(ps); 125 sock_setblocking(ps);
133 if (bind(*ps, addr, addr_len) < 0) err = sock_bindstrerror(errno); 126 if (bind(*ps, addr, addr_len) < 0) err = sock_strerror();
134 sock_setnonblocking(ps); 127 sock_setnonblocking(ps);
135 return err; 128 return err;
136} 129}
@@ -138,12 +131,10 @@ const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
138/*-------------------------------------------------------------------------*\ 131/*-------------------------------------------------------------------------*\
139* 132*
140\*-------------------------------------------------------------------------*/ 133\*-------------------------------------------------------------------------*/
141const char* sock_listen(p_sock ps, int backlog) 134const char* sock_listen(p_sock ps, int backlog) {
142{
143 const char *err = NULL; 135 const char *err = NULL;
144 sock_setblocking(ps); 136 sock_setblocking(ps);
145 if (listen(*ps, backlog)) 137 if (listen(*ps, backlog)) err = sock_strerror();
146 err = sock_listenstrerror(errno);
147 sock_setnonblocking(ps); 138 sock_setnonblocking(ps);
148 return err; 139 return err;
149} 140}
@@ -151,8 +142,7 @@ const char* sock_listen(p_sock ps, int backlog)
151/*-------------------------------------------------------------------------*\ 142/*-------------------------------------------------------------------------*\
152* 143*
153\*-------------------------------------------------------------------------*/ 144\*-------------------------------------------------------------------------*/
154void sock_shutdown(p_sock ps, int how) 145void sock_shutdown(p_sock ps, int how) {
155{
156 sock_setblocking(ps); 146 sock_setblocking(ps);
157 shutdown(*ps, how); 147 shutdown(*ps, how);
158 sock_setnonblocking(ps); 148 sock_setnonblocking(ps);
@@ -162,12 +152,11 @@ void sock_shutdown(p_sock ps, int how)
162* Accept with timeout 152* Accept with timeout
163\*-------------------------------------------------------------------------*/ 153\*-------------------------------------------------------------------------*/
164const char *sock_accept(p_sock ps, p_sock pa, SA *addr, 154const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
165 socklen_t *addr_len, p_tm tm) 155 socklen_t *addr_len, p_tm tm) {
166{
167 t_sock sock = *ps; 156 t_sock sock = *ps;
168 SA dummy_addr; 157 SA dummy_addr;
169 socklen_t dummy_len = sizeof(dummy_addr); 158 socklen_t dummy_len = sizeof(dummy_addr);
170 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); 159 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED);
171 if (!addr) addr = &dummy_addr; 160 if (!addr) addr = &dummy_addr;
172 if (!addr_len) addr_len = &dummy_len; 161 if (!addr_len) addr_len = &dummy_len;
173 for (;;) { 162 for (;;) {
@@ -179,14 +168,16 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
179 /* if result is valid, we are done */ 168 /* if result is valid, we are done */
180 if (*pa != SOCK_INVALID) return NULL; 169 if (*pa != SOCK_INVALID) return NULL;
181 /* find out if we failed for a fatal reason */ 170 /* find out if we failed for a fatal reason */
182 if (errno != EAGAIN && errno != ECONNABORTED) 171 /* if connection was aborted, we can try again if we have time */
183 return sock_acceptstrerror(errno); 172 if (errno != EAGAIN && errno != ECONNABORTED) return sock_strerror();
173 /* optimize for timeout = 0 case */
174 if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT);
184 /* call select to avoid busy-wait. */ 175 /* call select to avoid busy-wait. */
185 FD_ZERO(&fds); 176 FD_ZERO(&fds);
186 FD_SET(sock, &fds); 177 FD_SET(sock, &fds);
187 do err = sock_select(sock+1, &fds, NULL, NULL, tm_getretry(tm)); 178 err = sock_select(sock+1, &fds, NULL, NULL, tm);
188 while (err < 0 && errno == EINTR);
189 if (err == 0) return io_strerror(IO_TIMEOUT); 179 if (err == 0) return io_strerror(IO_TIMEOUT);
180 else if (err < 0) return sock_strerror();
190 } 181 }
191 return io_strerror(IO_TIMEOUT); /* can't get here */ 182 return io_strerror(IO_TIMEOUT); /* can't get here */
192} 183}
@@ -194,136 +185,136 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
194/*-------------------------------------------------------------------------*\ 185/*-------------------------------------------------------------------------*\
195* Send with timeout 186* Send with timeout
196\*-------------------------------------------------------------------------*/ 187\*-------------------------------------------------------------------------*/
197int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 188int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
198 int timeout)
199{ 189{
200 t_sock sock = *ps; 190 t_sock sock = *ps;
201 ssize_t put;
202 /* avoid making system calls on closed sockets */ 191 /* avoid making system calls on closed sockets */
203 if (sock == SOCK_INVALID) return IO_CLOSED; 192 if (sock == SOCK_INVALID) return IO_CLOSED;
204 /* make sure we repeat in case the call was interrupted */ 193 /* loop until we send something or we give up on error */
205 do put = send(sock, data, count, 0); 194 for ( ;; ) {
206 while (put < 0 && errno == EINTR);
207 /* deal with failure */
208 if (put <= 0) {
209 int ret; 195 int ret;
210 fd_set fds; 196 fd_set fds;
211 /* in any case, nothing has been sent */ 197 ssize_t put;
198 /* make sure we repeat in case the call was interrupted */
199 do put = send(sock, data, count, 0);
200 while (put < 0 && errno == EINTR);
201 /* if we sent something, get out */
202 if (put > 0) {
203 *sent = put;
204 return IO_DONE;
205 }
206 /* deal with failure */
212 *sent = 0; 207 *sent = 0;
213 /* only proceed to select if no error happened */
214 if (errno != EAGAIN) return IO_ERROR;
215 /* optimize for the timeout = 0 case */
216 if (timeout == 0) return IO_TIMEOUT;
217 /* here we know the connection has been closed */ 208 /* here we know the connection has been closed */
218 if (errno == EPIPE) return IO_CLOSED; 209 if (put < 0 && errno == EPIPE) return IO_CLOSED;
210 /* send shouldn't return zero and we can only proceed if
211 * there was no serious error */
212 if (put == 0 || errno != EAGAIN) return IO_USER;
213 /* optimize for the timeout = 0 case */
214 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
219 /* run select to avoid busy wait */ 215 /* run select to avoid busy wait */
220 FD_ZERO(&fds); 216 FD_ZERO(&fds);
221 FD_SET(sock, &fds); 217 FD_SET(sock, &fds);
222 ret = sock_select(sock+1, NULL, &fds, NULL, timeout); 218 ret = sock_select(sock+1, NULL, &fds, NULL, tm);
223 if (ret == 0) return IO_TIMEOUT; 219 if (ret == 0) return IO_TIMEOUT;
224 else if (ret > 0 || errno == EINTR) return IO_RETRY; 220 if (ret < 0) return IO_USER;
225 else return IO_ERROR; 221 /* otherwise, try sending again */
226 /* here we successfully sent something */ 222 }
227 } else {
228 *sent = put;
229 return IO_DONE;
230 }
231} 223}
232 224
233/*-------------------------------------------------------------------------*\ 225/*-------------------------------------------------------------------------*\
234* Sendto with timeout 226* Sendto with timeout
235\*-------------------------------------------------------------------------*/ 227\*-------------------------------------------------------------------------*/
236int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, 228int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
237 SA *addr, socklen_t addr_len, int timeout) 229 SA *addr, socklen_t addr_len, p_tm tm)
238{ 230{
239 t_sock sock = *ps; 231 t_sock sock = *ps;
240 ssize_t put; 232 /* avoid making system calls on closed sockets */
241 if (sock == SOCK_INVALID) return IO_CLOSED; 233 if (sock == SOCK_INVALID) return IO_CLOSED;
242 do put = sendto(sock, data, count, 0, addr, addr_len); 234 /* loop until we send something or we give up on error */
243 while (put < 0 && errno == EINTR); 235 for ( ;; ) {
244 if (put <= 0) {
245 int ret; 236 int ret;
246 fd_set fds; 237 fd_set fds;
238 ssize_t put;
239 do put = sendto(sock, data, count, 0, addr, addr_len);
240 while (put < 0 && errno == EINTR);
241 if (put > 0) {
242 *sent = put;
243 return IO_DONE;
244 }
247 *sent = 0; 245 *sent = 0;
248 if (errno != EAGAIN) return IO_ERROR; 246 if (put < 0 && errno == EPIPE) return IO_CLOSED;
249 if (timeout == 0) return IO_TIMEOUT; 247 if (put == 0 || errno != EAGAIN) return IO_USER;
250 if (errno == EPIPE) return IO_CLOSED; 248 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
251 FD_ZERO(&fds); 249 FD_ZERO(&fds);
252 FD_SET(sock, &fds); 250 FD_SET(sock, &fds);
253 ret = sock_select(sock+1, NULL, &fds, NULL, timeout); 251 ret = sock_select(sock+1, NULL, &fds, NULL, tm);
254 if (ret == 0) return IO_TIMEOUT; 252 if (ret == 0) return IO_TIMEOUT;
255 else if (ret > 0 || errno == EINTR) return IO_RETRY; 253 if (ret < 0) return IO_USER;
256 else return IO_ERROR; 254 }
257 } else {
258 *sent = put;
259 return IO_DONE;
260 }
261} 255}
262 256
263/*-------------------------------------------------------------------------*\ 257/*-------------------------------------------------------------------------*\
264* Receive with timeout 258* Receive with timeout
265\*-------------------------------------------------------------------------*/ 259\*-------------------------------------------------------------------------*/
266int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 260int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) {
267{
268 t_sock sock = *ps; 261 t_sock sock = *ps;
269 ssize_t taken;
270 if (sock == SOCK_INVALID) return IO_CLOSED; 262 if (sock == SOCK_INVALID) return IO_CLOSED;
271 do taken = read(sock, data, count); 263 for ( ;; ) {
272 while (taken < 0 && errno == EINTR);
273 if (taken <= 0) {
274 fd_set fds; 264 fd_set fds;
275 int ret; 265 int ret;
266 ssize_t taken;
267 do taken = read(sock, data, count);
268 while (taken < 0 && errno == EINTR);
269 if (taken > 0) {
270 *got = taken;
271 return IO_DONE;
272 }
276 *got = 0; 273 *got = 0;
277 if (taken == 0) return IO_CLOSED; 274 if (taken == 0) return IO_CLOSED;
278 if (errno != EAGAIN) return IO_ERROR; 275 if (errno != EAGAIN) return IO_USER;
279 if (timeout == 0) return IO_TIMEOUT; 276 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
280 FD_ZERO(&fds); 277 FD_ZERO(&fds);
281 FD_SET(sock, &fds); 278 FD_SET(sock, &fds);
282 ret = sock_select(sock+1, &fds, NULL, NULL, timeout); 279 ret = sock_select(sock+1, &fds, NULL, NULL, tm);
283 if (ret == 0) return IO_TIMEOUT; 280 if (ret == 0) return IO_TIMEOUT;
284 else if (ret > 0 || errno == EINTR) return IO_RETRY; 281 if (ret < 0) return IO_USER;
285 else return IO_ERROR; 282 }
286 } else {
287 *got = taken;
288 return IO_DONE;
289 }
290} 283}
291 284
292/*-------------------------------------------------------------------------*\ 285/*-------------------------------------------------------------------------*\
293* Recvfrom with timeout 286* Recvfrom with timeout
294\*-------------------------------------------------------------------------*/ 287\*-------------------------------------------------------------------------*/
295int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, 288int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
296 SA *addr, socklen_t *addr_len, int timeout) 289 SA *addr, socklen_t *addr_len, p_tm tm) {
297{
298 t_sock sock = *ps; 290 t_sock sock = *ps;
299 ssize_t taken;
300 if (sock == SOCK_INVALID) return IO_CLOSED; 291 if (sock == SOCK_INVALID) return IO_CLOSED;
301 do taken = recvfrom(sock, data, count, 0, addr, addr_len); 292 for ( ;; ) {
302 while (taken < 0 && errno == EINTR);
303 if (taken <= 0) {
304 fd_set fds; 293 fd_set fds;
305 int ret; 294 int ret;
295 ssize_t taken;
296 do taken = recvfrom(sock, data, count, 0, addr, addr_len);
297 while (taken < 0 && errno == EINTR);
298 if (taken > 0) {
299 *got = taken;
300 return IO_DONE;
301 }
306 *got = 0; 302 *got = 0;
307 if (taken == 0) return IO_CLOSED; 303 if (taken == 0) return IO_CLOSED;
308 if (errno != EAGAIN) return IO_ERROR; 304 if (errno != EAGAIN) return IO_USER;
309 if (timeout == 0) return IO_TIMEOUT; 305 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
310 FD_ZERO(&fds); 306 FD_ZERO(&fds);
311 FD_SET(sock, &fds); 307 FD_SET(sock, &fds);
312 ret = sock_select(sock+1, &fds, NULL, NULL, timeout); 308 ret = sock_select(sock+1, &fds, NULL, NULL, tm);
313 if (ret == 0) return IO_TIMEOUT; 309 if (ret == 0) return IO_TIMEOUT;
314 else if (ret > 0 || errno == EINTR) return IO_RETRY; 310 if (ret < 0) return IO_USER;
315 else return IO_ERROR; 311 }
316 } else {
317 *got = taken;
318 return IO_DONE;
319 }
320} 312}
321 313
322/*-------------------------------------------------------------------------*\ 314/*-------------------------------------------------------------------------*\
323* Put socket into blocking mode 315* Put socket into blocking mode
324\*-------------------------------------------------------------------------*/ 316\*-------------------------------------------------------------------------*/
325void sock_setblocking(p_sock ps) 317void sock_setblocking(p_sock ps) {
326{
327 int flags = fcntl(*ps, F_GETFL, 0); 318 int flags = fcntl(*ps, F_GETFL, 0);
328 flags &= (~(O_NONBLOCK)); 319 flags &= (~(O_NONBLOCK));
329 fcntl(*ps, F_SETFL, flags); 320 fcntl(*ps, F_SETFL, flags);
@@ -332,8 +323,7 @@ void sock_setblocking(p_sock ps)
332/*-------------------------------------------------------------------------*\ 323/*-------------------------------------------------------------------------*\
333* Put socket into non-blocking mode 324* Put socket into non-blocking mode
334\*-------------------------------------------------------------------------*/ 325\*-------------------------------------------------------------------------*/
335void sock_setnonblocking(p_sock ps) 326void sock_setnonblocking(p_sock ps) {
336{
337 int flags = fcntl(*ps, F_GETFL, 0); 327 int flags = fcntl(*ps, F_GETFL, 0);
338 flags |= O_NONBLOCK; 328 flags |= O_NONBLOCK;
339 fcntl(*ps, F_SETFL, flags); 329 fcntl(*ps, F_SETFL, flags);
@@ -342,98 +332,20 @@ void sock_setnonblocking(p_sock ps)
342/*-------------------------------------------------------------------------*\ 332/*-------------------------------------------------------------------------*\
343* Error translation functions 333* Error translation functions
344\*-------------------------------------------------------------------------*/ 334\*-------------------------------------------------------------------------*/
345/* return error messages for the known errors reported by gethostbyname */ 335const char *sock_hoststrerror(void) {
346const char *sock_hoststrerror(void) 336 return hstrerror(h_errno);
347{
348 switch (h_errno) {
349 case HOST_NOT_FOUND: return "host not found";
350 case NO_ADDRESS: return "valid host but no ip found";
351 case NO_RECOVERY: return "name server error";
352 case TRY_AGAIN: return "name server unavailable, try again later";
353 default: return "unknown error";
354 }
355}
356
357/* return error messages for the known errors reported by socket */
358static const char *sock_createstrerror(int err)
359{
360 switch (err) {
361 case EPROTONOSUPPORT: return "protocol not supported";
362 case EACCES: return "access denied";
363 case EMFILE: return "process file table is full";
364 case ENFILE: return "kernel file table is full";
365 case EINVAL: return "unknown protocol or family";
366 case ENOBUFS: return "insuffucient buffer space";
367 default: return "unknown error";
368 }
369} 337}
370 338
371/* return error messages for the known errors reported by accept */ 339/* make sure important error messages are standard */
372static const char *sock_acceptstrerror(int err) 340const char *sock_strerror(void) {
373{ 341 switch (errno) {
374 switch (err) { 342 case EADDRINUSE:
375 case EAGAIN: return io_strerror(IO_RETRY); 343 return "address already in use";
376 case EBADF: return "invalid descriptor"; 344 default:
377 case ENOBUFS: case ENOMEM: return "insuffucient buffer space"; 345 return strerror(errno);
378 case ENOTSOCK: return "descriptor not a socket";
379 case EOPNOTSUPP: return "not supported";
380 case EINTR: return "call interrupted";
381 case ECONNABORTED: return "connection aborted";
382 case EINVAL: return "not listening";
383 case EMFILE: return "process file table is full";
384 case ENFILE: return "kernel file table is full";
385 case EFAULT: return "invalid memory address";
386 default: return "unknown error";
387 }
388}
389
390
391/* return error messages for the known errors reported by bind */
392static const char *sock_bindstrerror(int err)
393{
394 switch (err) {
395 case EBADF: return "invalid descriptor";
396 case ENOTSOCK: return "descriptor not a socket";
397 case EADDRNOTAVAIL: return "address unavailable in local host";
398 case EADDRINUSE: return "address already in use";
399 case EINVAL: return "already bound";
400 case EACCES: return "access denied";
401 case EFAULT: return "invalid memory address";
402 case ENOMEM: return "out of memory";
403 default: return "unknown error";
404 } 346 }
405} 347}
406 348
407/* return error messages for the known errors reported by listen */ 349const char *sock_geterr(p_sock ps, int code) {
408static const char *sock_listenstrerror(int err) 350 return sock_strerror();
409{
410 switch (err) {
411 case EADDRINUSE: return "local address already in use";
412 case EBADF: return "invalid descriptor";
413 case ENOTSOCK: return "descriptor not a socket";
414 case EOPNOTSUPP: 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 EBADF: return "invalid descriptor";
424 case EFAULT: return "invalid memory address";
425 case ENOTSOCK: return "descriptor not a socket";
426 case EADDRNOTAVAIL: return "address not available in local host";
427 case EISCONN: return "already connected";
428 case ECONNREFUSED: return "connection refused";
429 case ETIMEDOUT: return io_strerror(IO_TIMEOUT);
430 case ENETUNREACH: return "network is unreachable";
431 case EADDRINUSE: return "local address already in use";
432 case EINPROGRESS: return "would block";
433 case EALREADY: return "connect already in progress";
434 case EAGAIN: return "not enough free ports";
435 case EAFNOSUPPORT: return "address family not supported";
436 case EPERM: return "broadcast not enabled or firewall block";
437 default: return "unknown error";
438 }
439} 351}
diff --git a/src/usocket.h b/src/usocket.h
index b9255cb..d3d4f48 100644
--- a/src/usocket.h
+++ b/src/usocket.h
@@ -16,14 +16,12 @@
16#include <unistd.h> 16#include <unistd.h>
17/* fnctnl function and associated constants */ 17/* fnctnl function and associated constants */
18#include <fcntl.h> 18#include <fcntl.h>
19/* struct timeval and CLK_TCK */
20#include <sys/time.h>
21/* times function and struct tms */
22#include <sys/times.h>
23/* struct sockaddr */ 19/* struct sockaddr */
24#include <sys/types.h> 20#include <sys/types.h>
25/* socket function */ 21/* socket function */
26#include <sys/socket.h> 22#include <sys/socket.h>
23/* struct timeval */
24#include <sys/time.h>
27/* gethostbyname and gethostbyaddr functions */ 25/* gethostbyname and gethostbyaddr functions */
28#include <netdb.h> 26#include <netdb.h>
29/* sigpipe handling */ 27/* sigpipe handling */