Killed a few bugs found by Tomas.

This commit is contained in:
Diego Nehab 2003-11-27 00:30:54 +00:00
parent 9bc4e0648a
commit 3febb302ad
10 changed files with 99 additions and 58 deletions

12
TODO
View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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);