diff options
| -rw-r--r-- | src/inet.c | 6 | ||||
| -rw-r--r-- | src/inet.h | 2 | ||||
| -rw-r--r-- | src/io.h | 1 | ||||
| -rw-r--r-- | src/socket.h | 2 | ||||
| -rw-r--r-- | src/tcp.c | 7 | ||||
| -rw-r--r-- | src/udp.c | 4 | ||||
| -rw-r--r-- | src/usocket.c | 59 | ||||
| -rw-r--r-- | src/wsocket.c | 7 |
8 files changed, 63 insertions, 25 deletions
| @@ -181,7 +181,7 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp) | |||
| 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, const char *address, |
| 184 | unsigned short port) | 184 | unsigned short port, int timeout) |
| 185 | { | 185 | { |
| 186 | struct sockaddr_in remote; | 186 | struct sockaddr_in remote; |
| 187 | const char *err; | 187 | const char *err; |
| @@ -197,14 +197,12 @@ 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 | sock_setblocking(ps); | 200 | err = sock_connect(ps, (SA *) &remote, sizeof(remote), timeout); |
| 201 | err = sock_connect(ps, (SA *) &remote, sizeof(remote)); | ||
| 202 | if (err) { | 201 | if (err) { |
| 203 | sock_destroy(ps); | 202 | sock_destroy(ps); |
| 204 | *ps = SOCK_INVALID; | 203 | *ps = SOCK_INVALID; |
| 205 | return err; | 204 | return err; |
| 206 | } else { | 205 | } else { |
| 207 | sock_setnonblocking(ps); | ||
| 208 | return NULL; | 206 | return NULL; |
| 209 | } | 207 | } |
| 210 | } | 208 | } |
| @@ -25,7 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | void inet_open(lua_State *L); | 26 | void inet_open(lua_State *L); |
| 27 | const char *inet_tryconnect(p_sock ps, const char *address, | 27 | const char *inet_tryconnect(p_sock ps, const char *address, |
| 28 | unsigned short port); | 28 | unsigned short port, int timeout); |
| 29 | const char *inet_trybind(p_sock ps, const char *address, | 29 | const char *inet_trybind(p_sock ps, const char *address, |
| 30 | unsigned short port, int backlog); | 30 | unsigned short port, int backlog); |
| 31 | const char *inet_trycreate(p_sock ps, int type); | 31 | const char *inet_trycreate(p_sock ps, int type); |
| @@ -24,6 +24,7 @@ enum { | |||
| 24 | IO_CLOSED, /* the connection has been closed */ | 24 | IO_CLOSED, /* the connection has been closed */ |
| 25 | IO_ERROR, /* something wrong... */ | 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_LIMITED /* maximum number of bytes reached */ | 28 | IO_LIMITED /* maximum number of bytes reached */ |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
diff --git a/src/socket.h b/src/socket.h index cea9e0d..aeadff0 100644 --- a/src/socket.h +++ b/src/socket.h | |||
| @@ -34,7 +34,7 @@ const char *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); | 37 | const char *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 | const char *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); |
| @@ -257,7 +257,10 @@ static int meth_connect(lua_State *L) | |||
| 257 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); | 257 | p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); |
| 258 | const char *address = luaL_checkstring(L, 2); | 258 | const char *address = luaL_checkstring(L, 2); |
| 259 | unsigned short port = (unsigned short) luaL_checknumber(L, 3); | 259 | unsigned short port = (unsigned short) luaL_checknumber(L, 3); |
| 260 | const char *err = inet_tryconnect(&tcp->sock, address, port); | 260 | p_tm tm = &tcp->tm; |
| 261 | const char *err; | ||
| 262 | tm_markstart(tm); | ||
| 263 | err = inet_tryconnect(&tcp->sock, address, port, tm_getfailure(tm)); | ||
| 261 | if (err) { | 264 | if (err) { |
| 262 | lua_pushnil(L); | 265 | lua_pushnil(L); |
| 263 | lua_pushstring(L, err); | 266 | lua_pushstring(L, err); |
| @@ -326,7 +329,7 @@ static int meth_getsockname(lua_State *L) | |||
| 326 | \*-------------------------------------------------------------------------*/ | 329 | \*-------------------------------------------------------------------------*/ |
| 327 | static int meth_settimeout(lua_State *L) | 330 | static int meth_settimeout(lua_State *L) |
| 328 | { | 331 | { |
| 329 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); | 332 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); |
| 330 | return tm_meth_settimeout(L, &tcp->tm); | 333 | return tm_meth_settimeout(L, &tcp->tm); |
| 331 | } | 334 | } |
| 332 | 335 | ||
| @@ -335,12 +335,14 @@ static int meth_settimeout(lua_State *L) | |||
| 335 | static int meth_setpeername(lua_State *L) | 335 | static int meth_setpeername(lua_State *L) |
| 336 | { | 336 | { |
| 337 | p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); | 337 | p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); |
| 338 | p_tm tm = &udp->tm; | ||
| 338 | const char *address = luaL_checkstring(L, 2); | 339 | const char *address = luaL_checkstring(L, 2); |
| 339 | int connecting = strcmp(address, "*"); | 340 | int connecting = strcmp(address, "*"); |
| 340 | unsigned short port = connecting ? | 341 | unsigned short port = connecting ? |
| 341 | (unsigned short) luaL_checknumber(L, 3) : | 342 | (unsigned short) luaL_checknumber(L, 3) : |
| 342 | (unsigned short) luaL_optnumber(L, 3, 0); | 343 | (unsigned short) luaL_optnumber(L, 3, 0); |
| 343 | const char *err = inet_tryconnect(&udp->sock, address, port); | 344 | const char *err; |
| 345 | err = inet_tryconnect(&udp->sock, address, port, tm_getfailure(tm)); | ||
| 344 | if (err) { | 346 | if (err) { |
| 345 | lua_pushnil(L); | 347 | lua_pushnil(L); |
| 346 | lua_pushstring(L, err); | 348 | lua_pushstring(L, err); |
diff --git a/src/usocket.c b/src/usocket.c index 89be85e..9fcf4e8 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -2,6 +2,17 @@ | |||
| 2 | * Socket compatibilization module for Unix | 2 | * Socket compatibilization module for Unix |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | * | 4 | * |
| 5 | * We are now treating EINTRs, but if an interrupt happens in the middle of | ||
| 6 | * a select function call, we don't guarantee values timeouts anymore. | ||
| 7 | * It's not a big deal, since we are not real-time anyways. | ||
| 8 | * | ||
| 9 | * We also exchanged the order of the calls to send/recv and select. | ||
| 10 | * The idea is that the outer loop (whoever is calling sock_send/recv) | ||
| 11 | * will call the function again if we didn't time out, so we can | ||
| 12 | * call write and then select only if it fails. This moves the penalty | ||
| 13 | * to when data is not available, maximizing the bandwidth if data is | ||
| 14 | * always available. | ||
| 15 | * | ||
| 5 | * RCS ID: $Id$ | 16 | * RCS ID: $Id$ |
| 6 | \*=========================================================================*/ | 17 | \*=========================================================================*/ |
| 7 | #include <string.h> | 18 | #include <string.h> |
| @@ -49,10 +60,27 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol) | |||
| 49 | /*-------------------------------------------------------------------------*\ | 60 | /*-------------------------------------------------------------------------*\ |
| 50 | * Connects or returns error message | 61 | * Connects or returns error message |
| 51 | \*-------------------------------------------------------------------------*/ | 62 | \*-------------------------------------------------------------------------*/ |
| 52 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) | 63 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) |
| 53 | { | 64 | { |
| 54 | if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); | 65 | t_sock sock = *ps; |
| 55 | else return NULL; | 66 | if (sock == SOCK_INVALID) return "closed"; |
| 67 | if (connect(sock, addr, addr_len) < 0) { | ||
| 68 | struct timeval tv; | ||
| 69 | fd_set wfds, efds; | ||
| 70 | int err; | ||
| 71 | tv.tv_sec = timeout / 1000; | ||
| 72 | tv.tv_usec = (timeout % 1000) * 1000; | ||
| 73 | FD_ZERO(&wfds); FD_ZERO(&efds); | ||
| 74 | FD_SET(sock, &wfds); FD_SET(sock, &efds); | ||
| 75 | do err = select(sock+1, NULL, &wfds, &efds, timeout >= 0 ? &tv : NULL); | ||
| 76 | while (err < 0 && errno == EINTR); | ||
| 77 | if (err <= 0) return "timeout"; | ||
| 78 | if (FD_ISSET(sock, &efds)) { | ||
| 79 | char dummy; | ||
| 80 | recv(sock, &dummy, 0, 0); | ||
| 81 | return sock_connectstrerror(); | ||
| 82 | } else return NULL; | ||
| 83 | } else return NULL; | ||
| 56 | } | 84 | } |
| 57 | 85 | ||
| 58 | /*-------------------------------------------------------------------------*\ | 86 | /*-------------------------------------------------------------------------*\ |
| @@ -91,14 +119,16 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 91 | SA dummy_addr; | 119 | SA dummy_addr; |
| 92 | socklen_t dummy_len; | 120 | socklen_t dummy_len; |
| 93 | fd_set fds; | 121 | fd_set fds; |
| 122 | int err; | ||
| 94 | if (sock == SOCK_INVALID) return IO_CLOSED; | 123 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 95 | tv.tv_sec = timeout / 1000; | 124 | tv.tv_sec = timeout / 1000; |
| 96 | tv.tv_usec = (timeout % 1000) * 1000; | 125 | tv.tv_usec = (timeout % 1000) * 1000; |
| 97 | FD_ZERO(&fds); | 126 | FD_ZERO(&fds); |
| 98 | FD_SET(sock, &fds); | 127 | FD_SET(sock, &fds); |
| 99 | *pa = SOCK_INVALID; | 128 | *pa = SOCK_INVALID; |
| 100 | if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) | 129 | do err = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 101 | return IO_TIMEOUT; | 130 | while (err < 0 && errno == EINTR); |
| 131 | if (err <= 0) return IO_TIMEOUT; | ||
| 102 | if (!addr) addr = &dummy_addr; | 132 | if (!addr) addr = &dummy_addr; |
| 103 | if (!addr_len) addr_len = &dummy_len; | 133 | if (!addr_len) addr_len = &dummy_len; |
| 104 | *pa = accept(sock, addr, addr_len); | 134 | *pa = accept(sock, addr, addr_len); |
| @@ -108,12 +138,6 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 108 | 138 | ||
| 109 | /*-------------------------------------------------------------------------*\ | 139 | /*-------------------------------------------------------------------------*\ |
| 110 | * Send with timeout | 140 | * Send with timeout |
| 111 | * Here we exchanged the order of the calls to write and select | ||
| 112 | * The idea is that the outer loop (whoever is calling sock_send) | ||
| 113 | * will call the function again if we didn't time out, so we can | ||
| 114 | * call write and then select only if it fails. | ||
| 115 | * Should speed things up! | ||
| 116 | * We are also treating EINTR and EPIPE errors. | ||
| 117 | \*-------------------------------------------------------------------------*/ | 141 | \*-------------------------------------------------------------------------*/ |
| 118 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | 142 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, |
| 119 | int timeout) | 143 | int timeout) |
| @@ -138,7 +162,8 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 138 | tv.tv_usec = (timeout % 1000) * 1000; | 162 | tv.tv_usec = (timeout % 1000) * 1000; |
| 139 | FD_ZERO(&fds); | 163 | FD_ZERO(&fds); |
| 140 | FD_SET(sock, &fds); | 164 | FD_SET(sock, &fds); |
| 141 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 165 | do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ?&tv : NULL); |
| 166 | while (ret < 0 && errno == EINTR); | ||
| 142 | /* tell the caller to call us again because there is more data */ | 167 | /* tell the caller to call us again because there is more data */ |
| 143 | if (ret > 0) return IO_DONE; | 168 | if (ret > 0) return IO_DONE; |
| 144 | /* tell the caller there was no data before timeout */ | 169 | /* tell the caller there was no data before timeout */ |
| @@ -178,7 +203,8 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 178 | tv.tv_usec = (timeout % 1000) * 1000; | 203 | tv.tv_usec = (timeout % 1000) * 1000; |
| 179 | FD_ZERO(&fds); | 204 | FD_ZERO(&fds); |
| 180 | FD_SET(sock, &fds); | 205 | FD_SET(sock, &fds); |
| 181 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 206 | do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL); |
| 207 | while (ret < 0 && errno == EINTR); | ||
| 182 | /* tell the caller to call us again because there is more data */ | 208 | /* tell the caller to call us again because there is more data */ |
| 183 | if (ret > 0) return IO_DONE; | 209 | if (ret > 0) return IO_DONE; |
| 184 | /* tell the caller there was no data before timeout */ | 210 | /* tell the caller there was no data before timeout */ |
| @@ -199,7 +225,6 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
| 199 | * will call the function again if we didn't time out, so we can | 225 | * will call the function again if we didn't time out, so we can |
| 200 | * call write and then select only if it fails. | 226 | * call write and then select only if it fails. |
| 201 | * Should speed things up! | 227 | * Should speed things up! |
| 202 | * We are also treating EINTR errors. | ||
| 203 | \*-------------------------------------------------------------------------*/ | 228 | \*-------------------------------------------------------------------------*/ |
| 204 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 229 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
| 205 | { | 230 | { |
| @@ -218,7 +243,8 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | |||
| 218 | tv.tv_usec = (timeout % 1000) * 1000; | 243 | tv.tv_usec = (timeout % 1000) * 1000; |
| 219 | FD_ZERO(&fds); | 244 | FD_ZERO(&fds); |
| 220 | FD_SET(sock, &fds); | 245 | FD_SET(sock, &fds); |
| 221 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 246 | do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 247 | while (ret < 0 && errno == EINTR); | ||
| 222 | if (ret > 0) return IO_DONE; | 248 | if (ret > 0) return IO_DONE; |
| 223 | else return IO_TIMEOUT; | 249 | else return IO_TIMEOUT; |
| 224 | } else { | 250 | } else { |
| @@ -248,7 +274,8 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
| 248 | tv.tv_usec = (timeout % 1000) * 1000; | 274 | tv.tv_usec = (timeout % 1000) * 1000; |
| 249 | FD_ZERO(&fds); | 275 | FD_ZERO(&fds); |
| 250 | FD_SET(sock, &fds); | 276 | FD_SET(sock, &fds); |
| 251 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 277 | do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); |
| 278 | while (ret < 0 && errno == EINTR); | ||
| 252 | if (ret > 0) return IO_DONE; | 279 | if (ret > 0) return IO_DONE; |
| 253 | else return IO_TIMEOUT; | 280 | else return IO_TIMEOUT; |
| 254 | } else { | 281 | } else { |
diff --git a/src/wsocket.c b/src/wsocket.c index 30208b9..bf92a90 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
| @@ -2,6 +2,13 @@ | |||
| 2 | * Socket compatibilization module for Win32 | 2 | * Socket compatibilization module for Win32 |
| 3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
| 4 | * | 4 | * |
| 5 | * We also exchanged the order of the calls to send/recv and select. | ||
| 6 | * The idea is that the outer loop (whoever is calling sock_send/recv) | ||
| 7 | * will call the function again if we didn't time out, so we can | ||
| 8 | * call write and then select only if it fails. This moves the penalty | ||
| 9 | * to when data is not available, maximizing the bandwidth if data is | ||
| 10 | * always available. | ||
| 11 | * | ||
| 5 | * RCS ID: $Id$ | 12 | * RCS ID: $Id$ |
| 6 | \*=========================================================================*/ | 13 | \*=========================================================================*/ |
| 7 | #include <string.h> | 14 | #include <string.h> |
