diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-18 00:04:20 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-18 00:04:20 +0000 |
| commit | c8d58798f0b0c789df5c566494112f81ac302432 (patch) | |
| tree | 40c52eab0a4bf92636ebe13027d165f0b8452bb1 /src | |
| parent | 02ef4e7daae6bef629dcb568052755fb85ed2efc (diff) | |
| download | luasocket-c8d58798f0b0c789df5c566494112f81ac302432.tar.gz luasocket-c8d58798f0b0c789df5c566494112f81ac302432.tar.bz2 luasocket-c8d58798f0b0c789df5c566494112f81ac302432.zip | |
Trying to get connect-with-timeout to work. Darwin works...
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer.c | 12 | ||||
| -rw-r--r-- | src/http.lua | 8 | ||||
| -rw-r--r-- | src/inet.c | 41 | ||||
| -rw-r--r-- | src/inet.h | 8 | ||||
| -rw-r--r-- | src/io.c | 35 | ||||
| -rw-r--r-- | src/io.h | 6 | ||||
| -rw-r--r-- | src/socket.h | 7 | ||||
| -rw-r--r-- | src/tcp.c | 69 | ||||
| -rw-r--r-- | src/timeout.c | 4 | ||||
| -rw-r--r-- | src/timeout.h | 4 | ||||
| -rw-r--r-- | src/udp.c | 64 | ||||
| -rw-r--r-- | src/usocket.c | 163 |
12 files changed, 227 insertions, 194 deletions
diff --git a/src/buffer.c b/src/buffer.c index 04419e7..e6d4ce8 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -138,8 +138,7 @@ int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) | |||
| 138 | int err = IO_DONE; | 138 | int err = IO_DONE; |
| 139 | while (total < count && err == IO_DONE) { | 139 | while (total < count && err == IO_DONE) { |
| 140 | size_t done; | 140 | size_t done; |
| 141 | err = io->send(io->ctx, data+total, count-total, &done, | 141 | err = io->send(io->ctx, data+total, count-total, &done, tm_get(tm)); |
| 142 | tm_getsuccess(tm)); | ||
| 143 | total += done; | 142 | total += done; |
| 144 | } | 143 | } |
| 145 | *sent = total; | 144 | *sent = total; |
| @@ -156,7 +155,7 @@ int recvraw(lua_State *L, p_buf buf, size_t wanted) | |||
| 156 | size_t total = 0; | 155 | size_t total = 0; |
| 157 | luaL_Buffer b; | 156 | luaL_Buffer b; |
| 158 | luaL_buffinit(L, &b); | 157 | luaL_buffinit(L, &b); |
| 159 | while (total < wanted && err == IO_DONE) { | 158 | while (total < wanted && (err == IO_DONE || err == IO_RETRY)) { |
| 160 | size_t count; const char *data; | 159 | size_t count; const char *data; |
| 161 | err = buf_get(buf, &data, &count); | 160 | err = buf_get(buf, &data, &count); |
| 162 | count = MIN(count, wanted - total); | 161 | count = MIN(count, wanted - total); |
| @@ -177,7 +176,7 @@ int recvall(lua_State *L, p_buf buf) | |||
| 177 | int err = IO_DONE; | 176 | int err = IO_DONE; |
| 178 | luaL_Buffer b; | 177 | luaL_Buffer b; |
| 179 | luaL_buffinit(L, &b); | 178 | luaL_buffinit(L, &b); |
| 180 | while (err == IO_DONE) { | 179 | while (err == IO_DONE || err == IO_RETRY) { |
| 181 | const char *data; size_t count; | 180 | const char *data; size_t count; |
| 182 | err = buf_get(buf, &data, &count); | 181 | err = buf_get(buf, &data, &count); |
| 183 | luaL_addlstring(&b, data, count); | 182 | luaL_addlstring(&b, data, count); |
| @@ -197,7 +196,7 @@ int recvline(lua_State *L, p_buf buf) | |||
| 197 | int err = IO_DONE; | 196 | int err = IO_DONE; |
| 198 | luaL_Buffer b; | 197 | luaL_Buffer b; |
| 199 | luaL_buffinit(L, &b); | 198 | luaL_buffinit(L, &b); |
| 200 | while (err == IO_DONE) { | 199 | while (err == IO_DONE || err == IO_RETRY) { |
| 201 | size_t count, pos; const char *data; | 200 | size_t count, pos; const char *data; |
| 202 | err = buf_get(buf, &data, &count); | 201 | err = buf_get(buf, &data, &count); |
| 203 | pos = 0; | 202 | pos = 0; |
| @@ -240,8 +239,7 @@ int buf_get(p_buf buf, const char **data, size_t *count) | |||
| 240 | p_tm tm = buf->tm; | 239 | p_tm tm = buf->tm; |
| 241 | if (buf_isempty(buf)) { | 240 | if (buf_isempty(buf)) { |
| 242 | size_t got; | 241 | size_t got; |
| 243 | err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, | 242 | err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm)); |
| 244 | tm_getsuccess(tm)); | ||
| 245 | buf->first = 0; | 243 | buf->first = 0; |
| 246 | buf->last = got; | 244 | buf->last = got; |
| 247 | } | 245 | } |
diff --git a/src/http.lua b/src/http.lua index 1925c68..2fc9e87 100644 --- a/src/http.lua +++ b/src/http.lua | |||
| @@ -549,10 +549,16 @@ function request_cb(reqt, respt) | |||
| 549 | reqt.headers = fill_headers(reqt.headers, parsed) | 549 | reqt.headers = fill_headers(reqt.headers, parsed) |
| 550 | -- try to connect to server | 550 | -- try to connect to server |
| 551 | local sock | 551 | local sock |
| 552 | sock, respt.error = socket.connect(parsed.host, parsed.port) | 552 | sock, respt.error = socket.tcp() |
| 553 | if not sock then return respt end | 553 | if not sock then return respt end |
| 554 | -- set connection timeout so that we do not hang forever | 554 | -- set connection timeout so that we do not hang forever |
| 555 | sock:settimeout(TIMEOUT) | 555 | sock:settimeout(TIMEOUT) |
| 556 | local ret | ||
| 557 | ret, respt.error = sock:connect(parsed.host, parsed.port) | ||
| 558 | if not ret then | ||
| 559 | sock:close() | ||
| 560 | return respt | ||
| 561 | end | ||
| 556 | -- send request message | 562 | -- send request message |
| 557 | respt.error = send_request(sock, reqt.method, | 563 | respt.error = send_request(sock, reqt.method, |
| 558 | request_uri(parsed), reqt.headers, reqt.body_cb) | 564 | request_uri(parsed), reqt.headers, reqt.body_cb) |
| @@ -180,11 +180,11 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp) | |||
| 180 | /*-------------------------------------------------------------------------*\ | 180 | /*-------------------------------------------------------------------------*\ |
| 181 | * Tries to connect to remote address (address, port) | 181 | * Tries to connect to remote address (address, port) |
| 182 | \*-------------------------------------------------------------------------*/ | 182 | \*-------------------------------------------------------------------------*/ |
| 183 | const char *inet_tryconnect(p_sock ps, const char *address, | 183 | const char *inet_tryconnect(p_sock ps, p_tm tm, const char *address, |
| 184 | unsigned short port, int timeout) | 184 | unsigned short port) |
| 185 | { | 185 | { |
| 186 | struct sockaddr_in remote; | 186 | struct sockaddr_in remote; |
| 187 | const char *err; | 187 | int err; |
| 188 | memset(&remote, 0, sizeof(remote)); | 188 | memset(&remote, 0, sizeof(remote)); |
| 189 | remote.sin_family = AF_INET; | 189 | remote.sin_family = AF_INET; |
| 190 | remote.sin_port = htons(port); | 190 | remote.sin_port = htons(port); |
| @@ -197,14 +197,14 @@ const char *inet_tryconnect(p_sock ps, const char *address, | |||
| 197 | memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr)); | 197 | memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr)); |
| 198 | } | 198 | } |
| 199 | } else remote.sin_family = AF_UNSPEC; | 199 | } else remote.sin_family = AF_UNSPEC; |
| 200 | err = sock_connect(ps, (SA *) &remote, sizeof(remote), timeout); | 200 | do err = sock_connect(ps, (SA *) &remote, sizeof(remote), tm_getretry(tm)); |
| 201 | if (err) { | 201 | while (err == IO_RETRY && tm_getretry(tm)); |
| 202 | if (err != IO_DONE) { | ||
| 202 | sock_destroy(ps); | 203 | sock_destroy(ps); |
| 203 | *ps = SOCK_INVALID; | 204 | *ps = SOCK_INVALID; |
| 204 | return err; | 205 | if (err == IO_ERROR) return sock_connectstrerror(); |
| 205 | } else { | 206 | else return io_strerror(err); |
| 206 | return NULL; | 207 | } else return NULL; |
| 207 | } | ||
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | /*-------------------------------------------------------------------------*\ | 210 | /*-------------------------------------------------------------------------*\ |
| @@ -214,7 +214,6 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port, | |||
| 214 | int backlog) | 214 | int backlog) |
| 215 | { | 215 | { |
| 216 | struct sockaddr_in local; | 216 | struct sockaddr_in local; |
| 217 | const char *err; | ||
| 218 | memset(&local, 0, sizeof(local)); | 217 | memset(&local, 0, sizeof(local)); |
| 219 | /* address is either wildcard or a valid ip address */ | 218 | /* address is either wildcard or a valid ip address */ |
| 220 | local.sin_addr.s_addr = htonl(INADDR_ANY); | 219 | local.sin_addr.s_addr = htonl(INADDR_ANY); |
| @@ -229,11 +228,10 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port, | |||
| 229 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); | 228 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); |
| 230 | } | 229 | } |
| 231 | sock_setblocking(ps); | 230 | sock_setblocking(ps); |
| 232 | err = sock_bind(ps, (SA *) &local, sizeof(local)); | 231 | if (sock_bind(ps, (SA *) &local, sizeof(local)) != IO_DONE) { |
| 233 | if (err) { | ||
| 234 | sock_destroy(ps); | 232 | sock_destroy(ps); |
| 235 | *ps = SOCK_INVALID; | 233 | *ps = SOCK_INVALID; |
| 236 | return err; | 234 | return sock_bindstrerror(); |
| 237 | } else { | 235 | } else { |
| 238 | sock_setnonblocking(ps); | 236 | sock_setnonblocking(ps); |
| 239 | if (backlog > 0) sock_listen(ps, backlog); | 237 | if (backlog > 0) sock_listen(ps, backlog); |
| @@ -246,7 +244,22 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port, | |||
| 246 | \*-------------------------------------------------------------------------*/ | 244 | \*-------------------------------------------------------------------------*/ |
| 247 | const char *inet_trycreate(p_sock ps, int type) | 245 | const char *inet_trycreate(p_sock ps, int type) |
| 248 | { | 246 | { |
| 249 | return sock_create(ps, AF_INET, type, 0); | 247 | if (sock_create(ps, AF_INET, type, 0) == IO_DONE) return NULL; |
| 248 | else return sock_createstrerror(); | ||
| 249 | } | ||
| 250 | |||
| 251 | /*-------------------------------------------------------------------------*\ | ||
| 252 | * Tries to accept an inet socket | ||
| 253 | \*-------------------------------------------------------------------------*/ | ||
| 254 | const char *inet_tryaccept(p_sock ps, p_tm tm, p_sock pc) | ||
| 255 | { | ||
| 256 | struct sockaddr_in addr; | ||
| 257 | socklen_t addr_len = sizeof(addr); | ||
| 258 | int err; | ||
| 259 | /* loop until connection accepted or timeout happens */ | ||
| 260 | do err = sock_accept(ps, pc, (SA *) &addr, &addr_len, tm_getretry(tm)); | ||
| 261 | while (err == IO_RETRY && tm_getretry(tm) != 0); | ||
| 262 | return io_strerror(err); | ||
| 250 | } | 263 | } |
| 251 | 264 | ||
| 252 | /*-------------------------------------------------------------------------*\ | 265 | /*-------------------------------------------------------------------------*\ |
| @@ -18,17 +18,21 @@ | |||
| 18 | \*=========================================================================*/ | 18 | \*=========================================================================*/ |
| 19 | #include <lua.h> | 19 | #include <lua.h> |
| 20 | #include "socket.h" | 20 | #include "socket.h" |
| 21 | #include "timeout.h" | ||
| 21 | 22 | ||
| 22 | #ifdef WIN32 | 23 | #ifdef WIN32 |
| 23 | #define INET_ATON | 24 | #define INET_ATON |
| 24 | #endif | 25 | #endif |
| 25 | 26 | ||
| 26 | void inet_open(lua_State *L); | 27 | void inet_open(lua_State *L); |
| 27 | const char *inet_tryconnect(p_sock ps, const char *address, | 28 | |
| 28 | unsigned short port, int timeout); | 29 | const char *inet_tryconnect(p_sock ps, p_tm tm, const char *address, |
| 30 | unsigned short port); | ||
| 29 | const char *inet_trybind(p_sock ps, const char *address, | 31 | const char *inet_trybind(p_sock ps, const char *address, |
| 30 | unsigned short port, int backlog); | 32 | unsigned short port, int backlog); |
| 31 | const char *inet_trycreate(p_sock ps, int type); | 33 | const char *inet_trycreate(p_sock ps, int type); |
| 34 | const char *inet_tryaccept(p_sock ps, p_tm tm, p_sock pc); | ||
| 35 | |||
| 32 | int inet_meth_getpeername(lua_State *L, p_sock ps); | 36 | int inet_meth_getpeername(lua_State *L, p_sock ps); |
| 33 | int inet_meth_getsockname(lua_State *L, p_sock ps); | 37 | int inet_meth_getsockname(lua_State *L, p_sock ps); |
| 34 | 38 | ||
| @@ -22,27 +22,24 @@ void io_init(p_io io, p_send send, p_recv recv, void *ctx) | |||
| 22 | /*-------------------------------------------------------------------------*\ | 22 | /*-------------------------------------------------------------------------*\ |
| 23 | * Translate error codes to Lua | 23 | * Translate error codes to Lua |
| 24 | \*-------------------------------------------------------------------------*/ | 24 | \*-------------------------------------------------------------------------*/ |
| 25 | void io_pusherror(lua_State *L, int code) | 25 | const char *io_strerror(int code) |
| 26 | { | 26 | { |
| 27 | switch (code) { | 27 | switch (code) { |
| 28 | case IO_DONE: | 28 | case IO_DONE: return NULL; |
| 29 | lua_pushnil(L); | 29 | case IO_TIMEOUT: return "timeout"; |
| 30 | break; | 30 | case IO_RETRY: return "retry"; |
| 31 | case IO_TIMEOUT: | 31 | case IO_CLOSED: return "closed"; |
| 32 | lua_pushstring(L, "timeout"); | 32 | case IO_REFUSED: return "refused"; |
| 33 | break; | 33 | default: return "unknown error"; |
| 34 | case IO_LIMITED: | ||
| 35 | lua_pushstring(L, "limited"); | ||
| 36 | break; | ||
| 37 | case IO_CLOSED: | ||
| 38 | lua_pushstring(L, "closed"); | ||
| 39 | break; | ||
| 40 | case IO_REFUSED: | ||
| 41 | lua_pushstring(L, "refused"); | ||
| 42 | break; | ||
| 43 | default: | ||
| 44 | lua_pushstring(L, "unknown error"); | ||
| 45 | break; | ||
| 46 | } | 34 | } |
| 47 | } | 35 | } |
| 48 | 36 | ||
| 37 | /*-------------------------------------------------------------------------*\ | ||
| 38 | * Translate error codes to Lua | ||
| 39 | \*-------------------------------------------------------------------------*/ | ||
| 40 | void io_pusherror(lua_State *L, int code) | ||
| 41 | { | ||
| 42 | const char *err = io_strerror(code); | ||
| 43 | if (err) lua_pushstring(L, err); | ||
| 44 | else lua_pushnil(L); | ||
| 45 | } | ||
| @@ -20,12 +20,11 @@ | |||
| 20 | /* IO error codes */ | 20 | /* IO error codes */ |
| 21 | enum { | 21 | enum { |
| 22 | IO_DONE, /* operation completed successfully */ | 22 | IO_DONE, /* operation completed successfully */ |
| 23 | IO_RETRY, /* please try again */ | ||
| 23 | IO_TIMEOUT, /* operation timed out */ | 24 | IO_TIMEOUT, /* operation timed out */ |
| 24 | IO_CLOSED, /* the connection has been closed */ | 25 | IO_CLOSED, /* the connection has been closed */ |
| 25 | IO_ERROR, /* something wrong... */ | ||
| 26 | IO_REFUSED, /* transfer has been refused */ | 26 | IO_REFUSED, /* transfer has been refused */ |
| 27 | IO_RETRY, /* please try again */ | 27 | IO_ERROR /* something else wrong... */ |
| 28 | IO_LIMITED /* maximum number of bytes reached */ | ||
| 29 | }; | 28 | }; |
| 30 | 29 | ||
| 31 | /* interface to send function */ | 30 | /* interface to send function */ |
| @@ -54,6 +53,7 @@ typedef struct t_io_ { | |||
| 54 | } t_io; | 53 | } t_io; |
| 55 | typedef t_io *p_io; | 54 | typedef t_io *p_io; |
| 56 | 55 | ||
| 56 | const char *io_strerror(int code); | ||
| 57 | void io_pusherror(lua_State *L, int code); | 57 | void io_pusherror(lua_State *L, int code); |
| 58 | void io_init(p_io io, p_send send, p_recv recv, void *ctx); | 58 | void io_init(p_io io, p_send send, p_recv recv, void *ctx); |
| 59 | 59 | ||
diff --git a/src/socket.h b/src/socket.h index aeadff0..739dedd 100644 --- a/src/socket.h +++ b/src/socket.h | |||
| @@ -30,12 +30,12 @@ typedef struct sockaddr SA; | |||
| 30 | * interface to sockets | 30 | * interface to sockets |
| 31 | \*=========================================================================*/ | 31 | \*=========================================================================*/ |
| 32 | int sock_open(void); | 32 | int sock_open(void); |
| 33 | const char *sock_create(p_sock ps, int domain, int type, int protocol); | 33 | int sock_create(p_sock ps, int domain, int type, int protocol); |
| 34 | void sock_destroy(p_sock ps); | 34 | void sock_destroy(p_sock ps); |
| 35 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | 35 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, |
| 36 | int timeout); | 36 | int timeout); |
| 37 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout); | 37 | int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout); |
| 38 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len); | 38 | int sock_bind(p_sock ps, SA *addr, socklen_t addr_len); |
| 39 | void sock_listen(p_sock ps, int backlog); | 39 | void sock_listen(p_sock ps, int backlog); |
| 40 | void sock_shutdown(p_sock ps, int how); | 40 | void sock_shutdown(p_sock ps, int how); |
| 41 | int sock_send(p_sock ps, const char *data, size_t count, | 41 | int sock_send(p_sock ps, const char *data, size_t count, |
| @@ -48,6 +48,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, | |||
| 48 | size_t *got, SA *addr, socklen_t *addr_len, int timeout); | 48 | size_t *got, SA *addr, socklen_t *addr_len, int timeout); |
| 49 | void sock_setnonblocking(p_sock ps); | 49 | void sock_setnonblocking(p_sock ps); |
| 50 | void sock_setblocking(p_sock ps); | 50 | void sock_setblocking(p_sock ps); |
| 51 | |||
| 51 | const char *sock_hoststrerror(void); | 52 | const char *sock_hoststrerror(void); |
| 52 | const char *sock_createstrerror(void); | 53 | const char *sock_createstrerror(void); |
| 53 | const char *sock_bindstrerror(void); | 54 | const char *sock_bindstrerror(void); |
| @@ -63,7 +63,7 @@ static luaL_reg tcp[] = { | |||
| 63 | static luaL_reg opt[] = { | 63 | static luaL_reg opt[] = { |
| 64 | {"keepalive", opt_keepalive}, | 64 | {"keepalive", opt_keepalive}, |
| 65 | {"reuseaddr", opt_reuseaddr}, | 65 | {"reuseaddr", opt_reuseaddr}, |
| 66 | {"tcp-nodelay", opt_tcp_nodelay}, | 66 | {"tcp-nodelay", opt_tcp_nodelay}, |
| 67 | {"linger", opt_linger}, | 67 | {"linger", opt_linger}, |
| 68 | {NULL, NULL} | 68 | {NULL, NULL} |
| 69 | }; | 69 | }; |
| @@ -200,32 +200,26 @@ static int meth_dirty(lua_State *L) | |||
| 200 | \*-------------------------------------------------------------------------*/ | 200 | \*-------------------------------------------------------------------------*/ |
| 201 | static int meth_accept(lua_State *L) | 201 | static int meth_accept(lua_State *L) |
| 202 | { | 202 | { |
| 203 | struct sockaddr_in addr; | ||
| 204 | socklen_t addr_len = sizeof(addr); | ||
| 205 | int err = IO_ERROR; | ||
| 206 | p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); | 203 | p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); |
| 207 | p_tm tm = &server->tm; | 204 | p_tm tm = &server->tm; |
| 208 | p_tcp client; | ||
| 209 | t_sock sock; | 205 | t_sock sock; |
| 210 | tm_markstart(tm); | 206 | tm_markstart(tm); |
| 211 | /* loop until connection accepted or timeout happens */ | 207 | const char *err = inet_tryaccept(&server->sock, tm, &sock); |
| 212 | while (err != IO_DONE) { | 208 | /* if successful, push client socket */ |
| 213 | err = sock_accept(&server->sock, &sock, | 209 | if (!err) { |
| 214 | (SA *) &addr, &addr_len, tm_getfailure(tm)); | 210 | p_tcp clnt = lua_newuserdata(L, sizeof(t_tcp)); |
| 215 | if (err == IO_CLOSED || (err == IO_TIMEOUT && !tm_getfailure(tm))) { | 211 | aux_setclass(L, "tcp{client}", -1); |
| 216 | lua_pushnil(L); | 212 | /* initialize structure fields */ |
| 217 | io_pusherror(L, err); | 213 | clnt->sock = sock; |
| 218 | return 2; | 214 | io_init(&clnt->io, (p_send)sock_send, (p_recv)sock_recv, &clnt->sock); |
| 219 | } | 215 | tm_init(&clnt->tm, -1, -1); |
| 216 | buf_init(&clnt->buf, &clnt->io, &clnt->tm); | ||
| 217 | return 1; | ||
| 218 | } else { | ||
| 219 | lua_pushnil(L); | ||
| 220 | lua_pushstring(L, err); | ||
| 221 | return 2; | ||
| 220 | } | 222 | } |
| 221 | client = lua_newuserdata(L, sizeof(t_tcp)); | ||
| 222 | aux_setclass(L, "tcp{client}", -1); | ||
| 223 | client->sock = sock; | ||
| 224 | /* initialize remaining structure fields */ | ||
| 225 | io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock); | ||
| 226 | tm_init(&client->tm, -1, -1); | ||
| 227 | buf_init(&client->buf, &client->io, &client->tm); | ||
| 228 | return 1; | ||
| 229 | } | 223 | } |
| 230 | 224 | ||
| 231 | /*-------------------------------------------------------------------------*\ | 225 | /*-------------------------------------------------------------------------*\ |
| @@ -260,7 +254,7 @@ static int meth_connect(lua_State *L) | |||
| 260 | p_tm tm = &tcp->tm; | 254 | p_tm tm = &tcp->tm; |
| 261 | const char *err; | 255 | const char *err; |
| 262 | tm_markstart(tm); | 256 | tm_markstart(tm); |
| 263 | err = inet_tryconnect(&tcp->sock, address, port, tm_getfailure(tm)); | 257 | err = inet_tryconnect(&tcp->sock, tm, address, port); |
| 264 | if (err) { | 258 | if (err) { |
| 265 | lua_pushnil(L); | 259 | lua_pushnil(L); |
| 266 | lua_pushstring(L, err); | 260 | lua_pushstring(L, err); |
| @@ -283,7 +277,7 @@ static int meth_close(lua_State *L) | |||
| 283 | } | 277 | } |
| 284 | 278 | ||
| 285 | /*-------------------------------------------------------------------------*\ | 279 | /*-------------------------------------------------------------------------*\ |
| 286 | * Shuts the connection down | 280 | * Shuts the connection down partially |
| 287 | \*-------------------------------------------------------------------------*/ | 281 | \*-------------------------------------------------------------------------*/ |
| 288 | static int meth_shutdown(lua_State *L) | 282 | static int meth_shutdown(lua_State *L) |
| 289 | { | 283 | { |
| @@ -341,22 +335,23 @@ static int meth_settimeout(lua_State *L) | |||
| 341 | \*-------------------------------------------------------------------------*/ | 335 | \*-------------------------------------------------------------------------*/ |
| 342 | int global_create(lua_State *L) | 336 | int global_create(lua_State *L) |
| 343 | { | 337 | { |
| 344 | const char *err; | 338 | t_sock sock; |
| 345 | /* allocate tcp object */ | 339 | const char *err = inet_trycreate(&sock, SOCK_STREAM); |
| 346 | p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); | ||
| 347 | /* set its type as master object */ | ||
| 348 | aux_setclass(L, "tcp{master}", -1); | ||
| 349 | /* try to allocate a system socket */ | 340 | /* try to allocate a system socket */ |
| 350 | err = inet_trycreate(&tcp->sock, SOCK_STREAM); | 341 | if (!err) { |
| 351 | if (err) { /* get rid of object on stack and push error */ | 342 | /* allocate tcp object */ |
| 352 | lua_pop(L, 1); | 343 | p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); |
| 344 | tcp->sock = sock; | ||
| 345 | /* set its type as master object */ | ||
| 346 | aux_setclass(L, "tcp{master}", -1); | ||
| 347 | /* initialize remaining structure fields */ | ||
| 348 | io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv, &tcp->sock); | ||
| 349 | tm_init(&tcp->tm, -1, -1); | ||
| 350 | buf_init(&tcp->buf, &tcp->io, &tcp->tm); | ||
| 351 | return 1; | ||
| 352 | } else { | ||
| 353 | lua_pushnil(L); | 353 | lua_pushnil(L); |
| 354 | lua_pushstring(L, err); | 354 | lua_pushstring(L, err); |
| 355 | return 2; | 355 | return 2; |
| 356 | } | 356 | } |
| 357 | /* initialize remaining structure fields */ | ||
| 358 | io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv, &tcp->sock); | ||
| 359 | tm_init(&tcp->tm, -1, -1); | ||
| 360 | buf_init(&tcp->buf, &tcp->io, &tcp->tm); | ||
| 361 | return 1; | ||
| 362 | } | 357 | } |
diff --git a/src/timeout.c b/src/timeout.c index 2d88ded..0063378 100644 --- a/src/timeout.c +++ b/src/timeout.c | |||
| @@ -54,7 +54,7 @@ void tm_init(p_tm tm, int block, int total) | |||
| 54 | * Returns | 54 | * Returns |
| 55 | * the number of ms left or -1 if there is no time limit | 55 | * the number of ms left or -1 if there is no time limit |
| 56 | \*-------------------------------------------------------------------------*/ | 56 | \*-------------------------------------------------------------------------*/ |
| 57 | int tm_getsuccess(p_tm tm) | 57 | int tm_get(p_tm tm) |
| 58 | { | 58 | { |
| 59 | if (tm->block < 0 && tm->total < 0) { | 59 | if (tm->block < 0 && tm->total < 0) { |
| 60 | return -1; | 60 | return -1; |
| @@ -89,7 +89,7 @@ int tm_getstart(p_tm tm) | |||
| 89 | * Returns | 89 | * Returns |
| 90 | * the number of ms left or -1 if there is no time limit | 90 | * the number of ms left or -1 if there is no time limit |
| 91 | \*-------------------------------------------------------------------------*/ | 91 | \*-------------------------------------------------------------------------*/ |
| 92 | int tm_getfailure(p_tm tm) | 92 | int tm_getretry(p_tm tm) |
| 93 | { | 93 | { |
| 94 | if (tm->block < 0 && tm->total < 0) { | 94 | if (tm->block < 0 && tm->total < 0) { |
| 95 | return -1; | 95 | return -1; |
diff --git a/src/timeout.h b/src/timeout.h index 17f44ea..0a036f4 100644 --- a/src/timeout.h +++ b/src/timeout.h | |||
| @@ -18,8 +18,8 @@ typedef t_tm *p_tm; | |||
| 18 | 18 | ||
| 19 | void tm_open(lua_State *L); | 19 | void tm_open(lua_State *L); |
| 20 | void tm_init(p_tm tm, int block, int total); | 20 | void tm_init(p_tm tm, int block, int total); |
| 21 | int tm_getsuccess(p_tm tm); | 21 | int tm_get(p_tm tm); |
| 22 | int tm_getfailure(p_tm tm); | 22 | int tm_getretry(p_tm tm); |
| 23 | void tm_markstart(p_tm tm); | 23 | void tm_markstart(p_tm tm); |
| 24 | int tm_getstart(p_tm tm); | 24 | int tm_getstart(p_tm tm); |
| 25 | int tm_gettime(void); | 25 | int tm_gettime(void); |
| @@ -29,6 +29,7 @@ static int meth_getpeername(lua_State *L); | |||
| 29 | static int meth_setsockname(lua_State *L); | 29 | static int meth_setsockname(lua_State *L); |
| 30 | static int meth_setpeername(lua_State *L); | 30 | static int meth_setpeername(lua_State *L); |
| 31 | static int meth_close(lua_State *L); | 31 | static int meth_close(lua_State *L); |
| 32 | static int meth_shutdown(lua_State *L); | ||
| 32 | static int meth_setoption(lua_State *L); | 33 | static int meth_setoption(lua_State *L); |
| 33 | static int meth_settimeout(lua_State *L); | 34 | static int meth_settimeout(lua_State *L); |
| 34 | static int meth_fd(lua_State *L); | 35 | static int meth_fd(lua_State *L); |
| @@ -53,6 +54,7 @@ static luaL_reg udp[] = { | |||
| 53 | {"receivefrom", meth_receivefrom}, | 54 | {"receivefrom", meth_receivefrom}, |
| 54 | {"settimeout", meth_settimeout}, | 55 | {"settimeout", meth_settimeout}, |
| 55 | {"close", meth_close}, | 56 | {"close", meth_close}, |
| 57 | {"shutdown", meth_shutdown}, | ||
| 56 | {"setoption", meth_setoption}, | 58 | {"setoption", meth_setoption}, |
| 57 | {"__gc", meth_close}, | 59 | {"__gc", meth_close}, |
| 58 | {"fd", meth_fd}, | 60 | {"fd", meth_fd}, |
| @@ -110,7 +112,7 @@ static int meth_send(lua_State *L) | |||
| 110 | int err; | 112 | int err; |
| 111 | const char *data = luaL_checklstring(L, 2, &count); | 113 | const char *data = luaL_checklstring(L, 2, &count); |
| 112 | tm_markstart(tm); | 114 | tm_markstart(tm); |
| 113 | err = sock_send(&udp->sock, data, count, &sent, tm_getsuccess(tm)); | 115 | err = sock_send(&udp->sock, data, count, &sent, tm_get(tm)); |
| 114 | if (err == IO_DONE) lua_pushnumber(L, sent); | 116 | if (err == IO_DONE) lua_pushnumber(L, sent); |
| 115 | else lua_pushnil(L); | 117 | else lua_pushnil(L); |
| 116 | /* a 'closed' error on an unconnected means the target address was not | 118 | /* a 'closed' error on an unconnected means the target address was not |
| @@ -139,7 +141,7 @@ static int meth_sendto(lua_State *L) | |||
| 139 | addr.sin_port = htons(port); | 141 | addr.sin_port = htons(port); |
| 140 | tm_markstart(tm); | 142 | tm_markstart(tm); |
| 141 | err = sock_sendto(&udp->sock, data, count, &sent, | 143 | err = sock_sendto(&udp->sock, data, count, &sent, |
| 142 | (SA *) &addr, sizeof(addr), tm_getsuccess(tm)); | 144 | (SA *) &addr, sizeof(addr), tm_get(tm)); |
| 143 | if (err == IO_DONE) lua_pushnumber(L, sent); | 145 | if (err == IO_DONE) lua_pushnumber(L, sent); |
| 144 | else lua_pushnil(L); | 146 | else lua_pushnil(L); |
| 145 | /* a 'closed' error on an unconnected means the target address was not | 147 | /* a 'closed' error on an unconnected means the target address was not |
| @@ -160,7 +162,7 @@ static int meth_receive(lua_State *L) | |||
| 160 | p_tm tm = &udp->tm; | 162 | p_tm tm = &udp->tm; |
| 161 | count = MIN(count, sizeof(buffer)); | 163 | count = MIN(count, sizeof(buffer)); |
| 162 | tm_markstart(tm); | 164 | tm_markstart(tm); |
| 163 | err = sock_recv(&udp->sock, buffer, count, &got, tm_getsuccess(tm)); | 165 | err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm)); |
| 164 | if (err == IO_DONE) lua_pushlstring(L, buffer, got); | 166 | if (err == IO_DONE) lua_pushlstring(L, buffer, got); |
| 165 | else lua_pushnil(L); | 167 | else lua_pushnil(L); |
| 166 | io_pusherror(L, err); | 168 | io_pusherror(L, err); |
| @@ -182,7 +184,7 @@ static int meth_receivefrom(lua_State *L) | |||
| 182 | tm_markstart(tm); | 184 | tm_markstart(tm); |
| 183 | count = MIN(count, sizeof(buffer)); | 185 | count = MIN(count, sizeof(buffer)); |
| 184 | err = sock_recvfrom(&udp->sock, buffer, count, &got, | 186 | err = sock_recvfrom(&udp->sock, buffer, count, &got, |
| 185 | (SA *) &addr, &addr_len, tm_getsuccess(tm)); | 187 | (SA *) &addr, &addr_len, tm_get(tm)); |
| 186 | if (err == IO_DONE) { | 188 | if (err == IO_DONE) { |
| 187 | lua_pushlstring(L, buffer, got); | 189 | lua_pushlstring(L, buffer, got); |
| 188 | lua_pushstring(L, inet_ntoa(addr.sin_addr)); | 190 | lua_pushstring(L, inet_ntoa(addr.sin_addr)); |
| @@ -341,8 +343,7 @@ static int meth_setpeername(lua_State *L) | |||
| 341 | unsigned short port = connecting ? | 343 | unsigned short port = connecting ? |
| 342 | (unsigned short) luaL_checknumber(L, 3) : | 344 | (unsigned short) luaL_checknumber(L, 3) : |
| 343 | (unsigned short) luaL_optnumber(L, 3, 0); | 345 | (unsigned short) luaL_optnumber(L, 3, 0); |
| 344 | const char *err; | 346 | const char *err = inet_tryconnect(&udp->sock, tm, address, port); |
| 345 | err = inet_tryconnect(&udp->sock, address, port, tm_getfailure(tm)); | ||
| 346 | if (err) { | 347 | if (err) { |
| 347 | lua_pushnil(L); | 348 | lua_pushnil(L); |
| 348 | lua_pushstring(L, err); | 349 | lua_pushstring(L, err); |
| @@ -366,6 +367,33 @@ static int meth_close(lua_State *L) | |||
| 366 | } | 367 | } |
| 367 | 368 | ||
| 368 | /*-------------------------------------------------------------------------*\ | 369 | /*-------------------------------------------------------------------------*\ |
| 370 | * Shuts the connection down partially | ||
| 371 | \*-------------------------------------------------------------------------*/ | ||
| 372 | static int meth_shutdown(lua_State *L) | ||
| 373 | { | ||
| 374 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); | ||
| 375 | const char *how = luaL_optstring(L, 2, "both"); | ||
| 376 | switch (how[0]) { | ||
| 377 | case 'b': | ||
| 378 | if (strcmp(how, "both")) goto error; | ||
| 379 | sock_shutdown(&udp->sock, 2); | ||
| 380 | break; | ||
| 381 | case 's': | ||
| 382 | if (strcmp(how, "send")) goto error; | ||
| 383 | sock_shutdown(&udp->sock, 1); | ||
| 384 | break; | ||
| 385 | case 'r': | ||
| 386 | if (strcmp(how, "receive")) goto error; | ||
| 387 | sock_shutdown(&udp->sock, 0); | ||
| 388 | break; | ||
| 389 | } | ||
| 390 | return 0; | ||
| 391 | error: | ||
| 392 | luaL_argerror(L, 2, "invalid shutdown method"); | ||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | |||
| 396 | /*-------------------------------------------------------------------------*\ | ||
| 369 | * Turns a master object into a server object | 397 | * Turns a master object into a server object |
| 370 | \*-------------------------------------------------------------------------*/ | 398 | \*-------------------------------------------------------------------------*/ |
| 371 | static int meth_setsockname(lua_State *L) | 399 | static int meth_setsockname(lua_State *L) |
| @@ -391,21 +419,21 @@ static int meth_setsockname(lua_State *L) | |||
| 391 | \*-------------------------------------------------------------------------*/ | 419 | \*-------------------------------------------------------------------------*/ |
| 392 | int global_create(lua_State *L) | 420 | int global_create(lua_State *L) |
| 393 | { | 421 | { |
| 394 | const char *err; | 422 | t_sock sock; |
| 395 | /* allocate udp object */ | 423 | const char *err = inet_trycreate(&sock, SOCK_DGRAM); |
| 396 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); | ||
| 397 | /* set its type as master object */ | ||
| 398 | aux_setclass(L, "udp{unconnected}", -1); | ||
| 399 | /* try to allocate a system socket */ | 424 | /* try to allocate a system socket */ |
| 400 | err = inet_trycreate(&udp->sock, SOCK_DGRAM); | 425 | if (!err) { |
| 401 | if (err) { | 426 | /* allocate tcp object */ |
| 402 | /* get rid of object on stack and push error */ | 427 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); |
| 403 | lua_pop(L, 1); | 428 | udp->sock = sock; |
| 429 | /* set its type as master object */ | ||
| 430 | aux_setclass(L, "udp{unconnected}", -1); | ||
| 431 | /* initialize remaining structure fields */ | ||
| 432 | tm_init(&udp->tm, -1, -1); | ||
| 433 | return 1; | ||
| 434 | } else { | ||
| 404 | lua_pushnil(L); | 435 | lua_pushnil(L); |
| 405 | lua_pushstring(L, err); | 436 | lua_pushstring(L, err); |
| 406 | return 2; | 437 | return 2; |
| 407 | } | 438 | } |
| 408 | /* initialize timeout management */ | ||
| 409 | tm_init(&udp->tm, -1, -1); | ||
| 410 | return 1; | ||
| 411 | } | 439 | } |
diff --git a/src/usocket.c b/src/usocket.c index 9fcf4e8..acac852 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -46,50 +46,59 @@ void sock_destroy(p_sock ps) | |||
| 46 | /*-------------------------------------------------------------------------*\ | 46 | /*-------------------------------------------------------------------------*\ |
| 47 | * Creates and sets up a socket | 47 | * Creates and sets up a socket |
| 48 | \*-------------------------------------------------------------------------*/ | 48 | \*-------------------------------------------------------------------------*/ |
| 49 | const char *sock_create(p_sock ps, int domain, int type, int protocol) | 49 | int sock_create(p_sock ps, int domain, int type, int protocol) |
| 50 | { | 50 | { |
| 51 | int val = 1; | 51 | int val = 1; |
| 52 | t_sock sock = socket(domain, type, protocol); | 52 | t_sock sock = socket(domain, type, protocol); |
| 53 | if (sock == SOCK_INVALID) return sock_createstrerror(); | 53 | if (sock == SOCK_INVALID) return IO_ERROR; |
| 54 | *ps = sock; | 54 | *ps = sock; |
| 55 | sock_setnonblocking(ps); | 55 | sock_setnonblocking(ps); |
| 56 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); | 56 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); |
| 57 | return NULL; | 57 | return IO_DONE; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /*-------------------------------------------------------------------------*\ | 60 | /*-------------------------------------------------------------------------*\ |
| 61 | * Connects or returns error message | 61 | * Connects or returns error message |
| 62 | \*-------------------------------------------------------------------------*/ | 62 | \*-------------------------------------------------------------------------*/ |
| 63 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) | 63 | int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) |
| 64 | { | 64 | { |
| 65 | t_sock sock = *ps; | 65 | t_sock sock = *ps; |
| 66 | if (sock == SOCK_INVALID) return "closed"; | 66 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 67 | /* if connect fails, we have to find out why */ | ||
| 67 | if (connect(sock, addr, addr_len) < 0) { | 68 | if (connect(sock, addr, addr_len) < 0) { |
| 68 | struct timeval tv; | 69 | struct timeval tv; |
| 69 | fd_set wfds, efds; | 70 | fd_set rfds, efds, wfds; |
| 70 | int err; | 71 | int err; |
| 72 | /* make sure the system is trying to connect */ | ||
| 73 | if (errno != EINPROGRESS) return IO_ERROR; | ||
| 71 | tv.tv_sec = timeout / 1000; | 74 | tv.tv_sec = timeout / 1000; |
| 72 | tv.tv_usec = (timeout % 1000) * 1000; | 75 | tv.tv_usec = (timeout % 1000) * 1000; |
| 73 | FD_ZERO(&wfds); FD_ZERO(&efds); | 76 | FD_ZERO(&rfds); FD_SET(sock, &rfds); |
| 74 | FD_SET(sock, &wfds); FD_SET(sock, &efds); | 77 | FD_ZERO(&wfds); FD_SET(sock, &wfds); |
| 75 | do err = select(sock+1, NULL, &wfds, &efds, timeout >= 0 ? &tv : NULL); | 78 | FD_ZERO(&efds); FD_SET(sock, &efds); |
| 76 | while (err < 0 && errno == EINTR); | 79 | /* we run select to avoid busy waiting */ |
| 77 | if (err <= 0) return "timeout"; | 80 | err = select(sock+1, &rfds, &wfds, &efds, timeout >= 0? &tv: NULL); |
| 78 | if (FD_ISSET(sock, &efds)) { | 81 | /* if select was interrupted, ask the user to retry */ |
| 82 | if (err < 0 && errno == EINTR) return IO_RETRY; | ||
| 83 | /* if selects readable, try reading */ | ||
| 84 | if (err > 0) { | ||
| 79 | char dummy; | 85 | char dummy; |
| 80 | recv(sock, &dummy, 0, 0); | 86 | /* try reading so that errno is set */ |
| 81 | return sock_connectstrerror(); | 87 | if (recv(sock, &dummy, 0, 0) < 0) return IO_ERROR; |
| 82 | } else return NULL; | 88 | return IO_DONE; |
| 83 | } else return NULL; | 89 | /* if no event happened, there was a timeout */ |
| 90 | } else return IO_TIMEOUT; | ||
| 91 | /* otherwise connection succeeded */ | ||
| 92 | } else return IO_DONE; | ||
| 84 | } | 93 | } |
| 85 | 94 | ||
| 86 | /*-------------------------------------------------------------------------*\ | 95 | /*-------------------------------------------------------------------------*\ |
| 87 | * Binds or returns error message | 96 | * Binds or returns error message |
| 88 | \*-------------------------------------------------------------------------*/ | 97 | \*-------------------------------------------------------------------------*/ |
| 89 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) | 98 | int sock_bind(p_sock ps, SA *addr, socklen_t addr_len) |
| 90 | { | 99 | { |
| 91 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); | 100 | if (bind(*ps, addr, addr_len) < 0) return IO_ERROR; |
| 92 | else return NULL; | 101 | else return IO_DONE; |
| 93 | } | 102 | } |
| 94 | 103 | ||
| 95 | /*-------------------------------------------------------------------------*\ | 104 | /*-------------------------------------------------------------------------*\ |
| @@ -115,25 +124,24 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 115 | int timeout) | 124 | int timeout) |
| 116 | { | 125 | { |
| 117 | t_sock sock = *ps; | 126 | t_sock sock = *ps; |
| 118 | struct timeval tv; | ||
| 119 | SA dummy_addr; | 127 | SA dummy_addr; |
| 120 | socklen_t dummy_len; | 128 | socklen_t dummy_len; |
| 121 | fd_set fds; | ||
| 122 | int err; | ||
| 123 | if (sock == SOCK_INVALID) return IO_CLOSED; | 129 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 124 | tv.tv_sec = timeout / 1000; | ||
| 125 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 126 | FD_ZERO(&fds); | ||
| 127 | FD_SET(sock, &fds); | ||
| 128 | *pa = SOCK_INVALID; | ||
| 129 | do err = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
| 130 | while (err < 0 && errno == EINTR); | ||
| 131 | if (err <= 0) return IO_TIMEOUT; | ||
| 132 | if (!addr) addr = &dummy_addr; | 130 | if (!addr) addr = &dummy_addr; |
| 133 | if (!addr_len) addr_len = &dummy_len; | 131 | if (!addr_len) addr_len = &dummy_len; |
| 134 | *pa = accept(sock, addr, addr_len); | 132 | *pa = accept(sock, addr, addr_len); |
| 135 | if (*pa == SOCK_INVALID) return IO_ERROR; | 133 | if (*pa == SOCK_INVALID) { |
| 136 | else return IO_DONE; | 134 | struct timeval tv; |
| 135 | fd_set fds; | ||
| 136 | tv.tv_sec = timeout / 1000; | ||
| 137 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 138 | FD_ZERO(&fds); | ||
| 139 | FD_SET(sock, &fds); | ||
| 140 | /* just call select to avoid busy-wait. doesn't really matter | ||
| 141 | * what happens. the caller will choose to retry or not */ | ||
| 142 | select(sock+1, &fds, NULL, NULL, timeout >= 0? &tv: NULL); | ||
| 143 | return IO_RETRY; | ||
| 144 | } else return IO_DONE; | ||
| 137 | } | 145 | } |
| 138 | 146 | ||
| 139 | /*-------------------------------------------------------------------------*\ | 147 | /*-------------------------------------------------------------------------*\ |
| @@ -144,32 +152,31 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 144 | { | 152 | { |
| 145 | t_sock sock = *ps; | 153 | t_sock sock = *ps; |
| 146 | ssize_t put; | 154 | ssize_t put; |
| 147 | int ret; | ||
| 148 | /* avoid making system calls on closed sockets */ | 155 | /* avoid making system calls on closed sockets */ |
| 149 | if (sock == SOCK_INVALID) return IO_CLOSED; | 156 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 150 | /* make sure we repeat in case the call was interrupted */ | 157 | /* make sure we repeat in case the call was interrupted */ |
| 151 | do put = write(sock, data, count); | 158 | do put = send(sock, data, count, 0); |
| 152 | while (put <= 0 && errno == EINTR); | 159 | while (put < 0 && errno == EINTR); |
| 153 | /* deal with failure */ | 160 | /* deal with failure */ |
| 154 | if (put <= 0) { | 161 | if (put <= 0) { |
| 162 | struct timeval tv; | ||
| 163 | fd_set fds; | ||
| 155 | /* in any case, nothing has been sent */ | 164 | /* in any case, nothing has been sent */ |
| 156 | *sent = 0; | 165 | *sent = 0; |
| 166 | /* here we know the connection has been closed */ | ||
| 167 | if (errno == EPIPE) return IO_CLOSED; | ||
| 157 | /* run select to avoid busy wait */ | 168 | /* run select to avoid busy wait */ |
| 158 | if (errno != EPIPE) { | 169 | tv.tv_sec = timeout / 1000; |
| 159 | struct timeval tv; | 170 | tv.tv_usec = (timeout % 1000) * 1000; |
| 160 | fd_set fds; | 171 | FD_ZERO(&fds); |
| 161 | tv.tv_sec = timeout / 1000; | 172 | FD_SET(sock, &fds); |
| 162 | tv.tv_usec = (timeout % 1000) * 1000; | 173 | if (select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL) <= 0) { |
| 163 | FD_ZERO(&fds); | 174 | /* here the call was interrupted. calling again might work */ |
| 164 | FD_SET(sock, &fds); | 175 | if (errno == EINTR) return IO_RETRY; |
| 165 | do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ?&tv : NULL); | 176 | /* here there was no data before timeout */ |
| 166 | while (ret < 0 && errno == EINTR); | ||
| 167 | /* tell the caller to call us again because there is more data */ | ||
| 168 | if (ret > 0) return IO_DONE; | ||
| 169 | /* tell the caller there was no data before timeout */ | ||
| 170 | else return IO_TIMEOUT; | 177 | else return IO_TIMEOUT; |
| 171 | /* here we know the connection has been closed */ | 178 | /* here we didn't send anything, but now we can */ |
| 172 | } else return IO_CLOSED; | 179 | } else return IO_DONE; |
| 173 | /* here we successfully sent something */ | 180 | /* here we successfully sent something */ |
| 174 | } else { | 181 | } else { |
| 175 | *sent = put; | 182 | *sent = put; |
| @@ -185,33 +192,22 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 185 | { | 192 | { |
| 186 | t_sock sock = *ps; | 193 | t_sock sock = *ps; |
| 187 | ssize_t put; | 194 | ssize_t put; |
| 188 | int ret; | ||
| 189 | /* avoid making system calls on closed sockets */ | ||
| 190 | if (sock == SOCK_INVALID) return IO_CLOSED; | 195 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 191 | /* make sure we repeat in case the call was interrupted */ | ||
| 192 | do put = sendto(sock, data, count, 0, addr, addr_len); | 196 | do put = sendto(sock, data, count, 0, addr, addr_len); |
| 193 | while (put <= 0 && errno == EINTR); | 197 | while (put < 0 && errno == EINTR); |
| 194 | /* deal with failure */ | ||
| 195 | if (put <= 0) { | 198 | if (put <= 0) { |
| 196 | /* in any case, nothing has been sent */ | 199 | struct timeval tv; |
| 200 | fd_set fds; | ||
| 197 | *sent = 0; | 201 | *sent = 0; |
| 198 | /* run select to avoid busy wait */ | 202 | if (errno == EPIPE) return IO_CLOSED; |
| 199 | if (errno != EPIPE) { | 203 | tv.tv_sec = timeout / 1000; |
| 200 | struct timeval tv; | 204 | tv.tv_usec = (timeout % 1000) * 1000; |
| 201 | fd_set fds; | 205 | FD_ZERO(&fds); |
| 202 | tv.tv_sec = timeout / 1000; | 206 | FD_SET(sock, &fds); |
| 203 | tv.tv_usec = (timeout % 1000) * 1000; | 207 | if (select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL) <= 0) { |
| 204 | FD_ZERO(&fds); | 208 | if (errno == EINTR) return IO_RETRY; |
| 205 | FD_SET(sock, &fds); | ||
| 206 | do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL); | ||
| 207 | while (ret < 0 && errno == EINTR); | ||
| 208 | /* tell the caller to call us again because there is more data */ | ||
| 209 | if (ret > 0) return IO_DONE; | ||
| 210 | /* tell the caller there was no data before timeout */ | ||
| 211 | else return IO_TIMEOUT; | 209 | else return IO_TIMEOUT; |
| 212 | /* here we know the connection has been closed */ | 210 | } else return IO_DONE; |
| 213 | } else return IO_CLOSED; | ||
| 214 | /* here we successfully sent something */ | ||
| 215 | } else { | 211 | } else { |
| 216 | *sent = put; | 212 | *sent = put; |
| 217 | return IO_DONE; | 213 | return IO_DONE; |
| @@ -220,11 +216,6 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 220 | 216 | ||
| 221 | /*-------------------------------------------------------------------------*\ | 217 | /*-------------------------------------------------------------------------*\ |
| 222 | * Receive with timeout | 218 | * Receive with timeout |
| 223 | * Here we exchanged the order of the calls to write and select | ||
| 224 | * The idea is that the outer loop (whoever is calling sock_send) | ||
| 225 | * will call the function again if we didn't time out, so we can | ||
| 226 | * call write and then select only if it fails. | ||
| 227 | * Should speed things up! | ||
| 228 | \*-------------------------------------------------------------------------*/ | 219 | \*-------------------------------------------------------------------------*/ |
| 229 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 220 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
| 230 | { | 221 | { |
| @@ -232,7 +223,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | |||
| 232 | ssize_t taken; | 223 | ssize_t taken; |
| 233 | if (sock == SOCK_INVALID) return IO_CLOSED; | 224 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 234 | do taken = read(sock, data, count); | 225 | do taken = read(sock, data, count); |
| 235 | while (taken <= 0 && errno == EINTR); | 226 | while (taken < 0 && errno == EINTR); |
| 236 | if (taken <= 0) { | 227 | if (taken <= 0) { |
| 237 | struct timeval tv; | 228 | struct timeval tv; |
| 238 | fd_set fds; | 229 | fd_set fds; |
| @@ -243,10 +234,10 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | |||
| 243 | tv.tv_usec = (timeout % 1000) * 1000; | 234 | tv.tv_usec = (timeout % 1000) * 1000; |
| 244 | FD_ZERO(&fds); | 235 | FD_ZERO(&fds); |
| 245 | FD_SET(sock, &fds); | 236 | FD_SET(sock, &fds); |
| 246 | do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 237 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 247 | while (ret < 0 && errno == EINTR); | 238 | if (ret < 0 && errno == EINTR) return IO_RETRY; |
| 248 | if (ret > 0) return IO_DONE; | 239 | if (ret == 0) return IO_TIMEOUT; |
| 249 | else return IO_TIMEOUT; | 240 | else return IO_DONE; |
| 250 | } else { | 241 | } else { |
| 251 | *got = taken; | 242 | *got = taken; |
| 252 | return IO_DONE; | 243 | return IO_DONE; |
| @@ -263,7 +254,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 263 | ssize_t taken; | 254 | ssize_t taken; |
| 264 | if (sock == SOCK_INVALID) return IO_CLOSED; | 255 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 265 | do taken = recvfrom(sock, data, count, 0, addr, addr_len); | 256 | do taken = recvfrom(sock, data, count, 0, addr, addr_len); |
| 266 | while (taken <= 0 && errno == EINTR); | 257 | while (taken < 0 && errno == EINTR); |
| 267 | if (taken <= 0) { | 258 | if (taken <= 0) { |
| 268 | struct timeval tv; | 259 | struct timeval tv; |
| 269 | fd_set fds; | 260 | fd_set fds; |
| @@ -274,10 +265,10 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 274 | tv.tv_usec = (timeout % 1000) * 1000; | 265 | tv.tv_usec = (timeout % 1000) * 1000; |
| 275 | FD_ZERO(&fds); | 266 | FD_ZERO(&fds); |
| 276 | FD_SET(sock, &fds); | 267 | FD_SET(sock, &fds); |
| 277 | do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 268 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 278 | while (ret < 0 && errno == EINTR); | 269 | if (ret < 0 && errno == EINTR) return IO_RETRY; |
| 279 | if (ret > 0) return IO_DONE; | 270 | if (ret == 0) return IO_TIMEOUT; |
| 280 | else return IO_TIMEOUT; | 271 | else return IO_DONE; |
| 281 | } else { | 272 | } else { |
| 282 | *got = taken; | 273 | *got = taken; |
| 283 | return IO_DONE; | 274 | return IO_DONE; |
