mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-26 04:28:20 +01:00
Killed a few bugs found by Tomas.
This commit is contained in:
parent
9bc4e0648a
commit
3febb302ad
12
TODO
12
TODO
@ -1,3 +1,15 @@
|
||||
replace times by getrusage
|
||||
|
||||
make sure modules know if their dependencies are there.
|
||||
|
||||
one thing i noticed in usocket.c is that it doesn't check for EINTR
|
||||
after write(), sendto(), read(), recvfrom() etc. ? the usual trick is
|
||||
to loop while you get EINTR:
|
||||
|
||||
do
|
||||
ret = write(...);
|
||||
while(ret < 0 && errno == EINTR)
|
||||
|
||||
|
||||
Read about
|
||||
|
||||
|
@ -138,7 +138,8 @@ int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
|
||||
int err = IO_DONE;
|
||||
while (total < count && err == IO_DONE) {
|
||||
size_t done;
|
||||
err = io->send(io->ctx, data+total, count-total, &done, tm_get(tm));
|
||||
err = io->send(io->ctx, data+total, count-total, &done,
|
||||
tm_getsuccess(tm));
|
||||
total += done;
|
||||
}
|
||||
*sent = total;
|
||||
@ -239,7 +240,8 @@ int buf_get(p_buf buf, const char **data, size_t *count)
|
||||
p_tm tm = buf->tm;
|
||||
if (buf_isempty(buf)) {
|
||||
size_t got;
|
||||
err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm));
|
||||
err = io->recv(io->ctx, buf->data, BUF_SIZE, &got,
|
||||
tm_getsuccess(tm));
|
||||
buf->first = 0;
|
||||
buf->last = got;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ Public.TIMEOUT = 60
|
||||
-- default port for document retrieval
|
||||
Public.PORT = 80
|
||||
-- user agent field sent in request
|
||||
Public.USERAGENT = "LuaSocket 1.5"
|
||||
Public.USERAGENT = "LuaSocket 2.0"
|
||||
-- block size used in transfers
|
||||
Public.BLOCKSIZE = 8192
|
||||
|
||||
@ -193,7 +193,8 @@ function Private.receivebody_bylength(sock, length, receive_cb)
|
||||
while length > 0 do
|
||||
local size = math.min(Public.BLOCKSIZE, length)
|
||||
local chunk, err = sock:receive(size)
|
||||
if err then
|
||||
-- if there was an error before we got all the data
|
||||
if err and string.len(chunk) ~= length then
|
||||
go, uerr = receive_cb(nil, err)
|
||||
return uerr or err
|
||||
end
|
||||
|
16
src/tcp.c
16
src/tcp.c
@ -198,21 +198,21 @@ static int meth_accept(lua_State *L)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
int err = IO_ERROR;
|
||||
p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
|
||||
p_tm tm = &server->tm;
|
||||
p_tcp client = lua_newuserdata(L, sizeof(t_tcp));
|
||||
tm_markstart(tm);
|
||||
aux_setclass(L, "tcp{client}", -1);
|
||||
for ( ;; ) {
|
||||
sock_accept(&server->sock, &client->sock,
|
||||
(SA *) &addr, &addr_len, tm_get(tm));
|
||||
if (client->sock == SOCK_INVALID) {
|
||||
if (tm_get(tm) == 0) {
|
||||
tm_markstart(tm);
|
||||
/* loop until connection accepted or timeout happens */
|
||||
while (err != IO_DONE) {
|
||||
err = sock_accept(&server->sock, &client->sock,
|
||||
(SA *) &addr, &addr_len, tm_getfailure(tm));
|
||||
if (err == IO_CLOSED || (err == IO_TIMEOUT && !tm_getfailure(tm))) {
|
||||
lua_pushnil(L);
|
||||
io_pusherror(L, IO_TIMEOUT);
|
||||
io_pusherror(L, err);
|
||||
return 2;
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
/* initialize remaining structure fields */
|
||||
io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock);
|
||||
|
@ -16,8 +16,8 @@
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
@ -46,40 +46,62 @@ void tm_init(p_tm tm, int block, int total)
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Set and get timeout limits
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void tm_setblock(p_tm tm, int block)
|
||||
{ tm->block = block; }
|
||||
void tm_settotal(p_tm tm, int total)
|
||||
{ tm->total = total; }
|
||||
int tm_getblock(p_tm tm)
|
||||
{ return tm->block; }
|
||||
int tm_gettotal(p_tm tm)
|
||||
{ return tm->total; }
|
||||
int tm_getstart(p_tm tm)
|
||||
{ return tm->start; }
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Determines how much time we have left for the current operation
|
||||
* Determines how much time we have left for the next system call,
|
||||
* if the previous call was successful
|
||||
* Input
|
||||
* tm: timeout control structure
|
||||
* Returns
|
||||
* the number of ms left or -1 if there is no time limit
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int tm_get(p_tm tm)
|
||||
int tm_getsuccess(p_tm tm)
|
||||
{
|
||||
/* no timeout */
|
||||
if (tm->block < 0 && tm->total < 0)
|
||||
if (tm->block < 0 && tm->total < 0) {
|
||||
return -1;
|
||||
/* there is no block timeout, we use the return timeout */
|
||||
else if (tm->block < 0)
|
||||
return MAX(tm->total - tm_gettime() + tm->start, 0);
|
||||
/* there is no return timeout, we use the block timeout */
|
||||
else if (tm->total < 0)
|
||||
} else if (tm->block < 0) {
|
||||
int t = tm->total - tm_gettime() + tm->start;
|
||||
return MAX(t, 0);
|
||||
} else if (tm->total < 0) {
|
||||
return tm->block;
|
||||
/* both timeouts are specified */
|
||||
else return MIN(tm->block,
|
||||
MAX(tm->total - tm_gettime() + tm->start, 0));
|
||||
} else {
|
||||
int t = tm->total - tm_gettime() + tm->start;
|
||||
return MIN(tm->block, MAX(t, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Returns time since start of operation
|
||||
* Input
|
||||
* tm: timeout control structure
|
||||
* Returns
|
||||
* start field of structure
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int tm_getstart(p_tm tm)
|
||||
{
|
||||
return tm->start;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Determines how much time we have left for the next system call,
|
||||
* if the previous call was a failure
|
||||
* Input
|
||||
* tm: timeout control structure
|
||||
* Returns
|
||||
* the number of ms left or -1 if there is no time limit
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int tm_getfailure(p_tm tm)
|
||||
{
|
||||
if (tm->block < 0 && tm->total < 0) {
|
||||
return -1;
|
||||
} else if (tm->block < 0) {
|
||||
int t = tm->total - tm_gettime() + tm->start;
|
||||
return MAX(t, 0);
|
||||
} else if (tm->total < 0) {
|
||||
int t = tm->block - tm_gettime() + tm->start;
|
||||
return MAX(t, 0);
|
||||
} else {
|
||||
int t = tm->total - tm_gettime() + tm->start;
|
||||
return MIN(tm->block, MAX(t, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
@ -131,10 +153,10 @@ int tm_meth_settimeout(lua_State *L, p_tm tm)
|
||||
const char *mode = luaL_optstring(L, 3, "b");
|
||||
switch (*mode) {
|
||||
case 'b':
|
||||
tm_setblock(tm, ms);
|
||||
tm->block = ms;
|
||||
break;
|
||||
case 'r': case 't':
|
||||
tm_settotal(tm, ms);
|
||||
tm->total = ms;
|
||||
break;
|
||||
default:
|
||||
luaL_argcheck(L, 0, 3, "invalid timeout mode");
|
||||
|
@ -18,13 +18,10 @@ typedef t_tm *p_tm;
|
||||
|
||||
void tm_open(lua_State *L);
|
||||
void tm_init(p_tm tm, int block, int total);
|
||||
void tm_setblock(p_tm tm, int block);
|
||||
void tm_settotal(p_tm tm, int total);
|
||||
int tm_getblock(p_tm tm);
|
||||
int tm_gettotal(p_tm tm);
|
||||
int tm_getsuccess(p_tm tm);
|
||||
int tm_getfailure(p_tm tm);
|
||||
void tm_markstart(p_tm tm);
|
||||
int tm_getstart(p_tm tm);
|
||||
int tm_get(p_tm tm);
|
||||
int tm_gettime(void);
|
||||
int tm_meth_settimeout(lua_State *L, p_tm tm);
|
||||
|
||||
|
@ -100,7 +100,7 @@ static int meth_send(lua_State *L)
|
||||
int err;
|
||||
const char *data = luaL_checklstring(L, 2, &count);
|
||||
tm_markstart(tm);
|
||||
err = sock_send(&udp->sock, data, count, &sent, tm_get(tm));
|
||||
err = sock_send(&udp->sock, data, count, &sent, tm_getsuccess(tm));
|
||||
if (err == IO_DONE) lua_pushnumber(L, sent);
|
||||
else lua_pushnil(L);
|
||||
/* a 'closed' error on an unconnected means the target address was not
|
||||
@ -129,7 +129,7 @@ static int meth_sendto(lua_State *L)
|
||||
addr.sin_port = htons(port);
|
||||
tm_markstart(tm);
|
||||
err = sock_sendto(&udp->sock, data, count, &sent,
|
||||
(SA *) &addr, sizeof(addr), tm_get(tm));
|
||||
(SA *) &addr, sizeof(addr), tm_getsuccess(tm));
|
||||
if (err == IO_DONE) lua_pushnumber(L, sent);
|
||||
else lua_pushnil(L);
|
||||
/* a 'closed' error on an unconnected means the target address was not
|
||||
@ -150,7 +150,7 @@ static int meth_receive(lua_State *L)
|
||||
p_tm tm = &udp->tm;
|
||||
count = MIN(count, sizeof(buffer));
|
||||
tm_markstart(tm);
|
||||
err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm));
|
||||
err = sock_recv(&udp->sock, buffer, count, &got, tm_getsuccess(tm));
|
||||
if (err == IO_DONE) lua_pushlstring(L, buffer, got);
|
||||
else lua_pushnil(L);
|
||||
io_pusherror(L, err);
|
||||
@ -172,7 +172,7 @@ static int meth_receivefrom(lua_State *L)
|
||||
tm_markstart(tm);
|
||||
count = MIN(count, sizeof(buffer));
|
||||
err = sock_recvfrom(&udp->sock, buffer, count, &got,
|
||||
(SA *) &addr, &addr_len, tm_get(tm));
|
||||
(SA *) &addr, &addr_len, tm_getsuccess(tm));
|
||||
if (err == IO_DONE) {
|
||||
lua_pushlstring(L, buffer, got);
|
||||
lua_pushstring(L, inet_ntoa(addr.sin_addr));
|
||||
|
@ -83,10 +83,12 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
|
||||
SA dummy_addr;
|
||||
socklen_t dummy_len;
|
||||
fd_set fds;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
*pa = SOCK_INVALID;
|
||||
if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
|
||||
return IO_TIMEOUT;
|
||||
if (!addr) addr = &dummy_addr;
|
||||
@ -108,6 +110,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
|
||||
ssize_t put = 0;
|
||||
int err;
|
||||
int ret;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
@ -145,6 +148,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
|
||||
ssize_t put = 0;
|
||||
int err;
|
||||
int ret;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
@ -180,6 +184,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
|
||||
fd_set fds;
|
||||
int ret;
|
||||
ssize_t taken = 0;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
@ -210,6 +215,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
int ret;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
ssize_t taken = 0;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
|
@ -34,11 +34,6 @@
|
||||
/* TCP options (nagle algorithm disable) */
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* for some reason socklen_t is not defined in Mac Os X */
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
typedef int t_sock;
|
||||
typedef t_sock *p_sock;
|
||||
|
||||
|
@ -86,10 +86,12 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
|
||||
SA dummy_addr;
|
||||
socklen_t dummy_len;
|
||||
fd_set fds;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
*pa = SOCK_INVALID;
|
||||
if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
|
||||
return IO_TIMEOUT;
|
||||
if (!addr) addr = &dummy_addr;
|
||||
@ -109,6 +111,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
ssize_t put = 0;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
int err;
|
||||
int ret;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
@ -148,6 +151,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
|
||||
ssize_t put = 0;
|
||||
int err;
|
||||
int ret;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
@ -183,6 +187,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
|
||||
fd_set fds;
|
||||
int ret;
|
||||
ssize_t taken = 0;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
@ -214,6 +219,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
|
||||
fd_set fds;
|
||||
int ret;
|
||||
ssize_t taken = 0;
|
||||
if (sock == SOCK_INVALID) return IO_CLOSED;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
|
Loading…
Reference in New Issue
Block a user