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 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; int err = IO_DONE;
while (total < count && err == IO_DONE) { while (total < count && err == IO_DONE) {
size_t 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; total += done;
} }
*sent = total; *sent = total;
@ -239,7 +240,8 @@ int buf_get(p_buf buf, const char **data, size_t *count)
p_tm tm = buf->tm; p_tm tm = buf->tm;
if (buf_isempty(buf)) { if (buf_isempty(buf)) {
size_t got; 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->first = 0;
buf->last = got; buf->last = got;
} }

View File

@ -18,7 +18,7 @@ Public.TIMEOUT = 60
-- default port for document retrieval -- default port for document retrieval
Public.PORT = 80 Public.PORT = 80
-- user agent field sent in request -- user agent field sent in request
Public.USERAGENT = "LuaSocket 1.5" Public.USERAGENT = "LuaSocket 2.0"
-- block size used in transfers -- block size used in transfers
Public.BLOCKSIZE = 8192 Public.BLOCKSIZE = 8192
@ -193,7 +193,8 @@ function Private.receivebody_bylength(sock, length, receive_cb)
while length > 0 do while length > 0 do
local size = math.min(Public.BLOCKSIZE, length) local size = math.min(Public.BLOCKSIZE, length)
local chunk, err = sock:receive(size) 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) go, uerr = receive_cb(nil, err)
return uerr or err return uerr or err
end end

View File

@ -198,21 +198,21 @@ static int meth_accept(lua_State *L)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr); socklen_t addr_len = sizeof(addr);
int err = IO_ERROR;
p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
p_tm tm = &server->tm; p_tm tm = &server->tm;
p_tcp client = lua_newuserdata(L, sizeof(t_tcp)); p_tcp client = lua_newuserdata(L, sizeof(t_tcp));
tm_markstart(tm);
aux_setclass(L, "tcp{client}", -1); aux_setclass(L, "tcp{client}", -1);
for ( ;; ) { tm_markstart(tm);
sock_accept(&server->sock, &client->sock, /* loop until connection accepted or timeout happens */
(SA *) &addr, &addr_len, tm_get(tm)); while (err != IO_DONE) {
if (client->sock == SOCK_INVALID) { err = sock_accept(&server->sock, &client->sock,
if (tm_get(tm) == 0) { (SA *) &addr, &addr_len, tm_getfailure(tm));
lua_pushnil(L); if (err == IO_CLOSED || (err == IO_TIMEOUT && !tm_getfailure(tm))) {
io_pusherror(L, IO_TIMEOUT); lua_pushnil(L);
return 2; io_pusherror(L, err);
} return 2;
} else break; }
} }
/* initialize remaining structure fields */ /* initialize remaining structure fields */
io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock); io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock);

View File

@ -16,8 +16,8 @@
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
#else #else
#include <sys/time.h>
#include <sys/times.h> #include <sys/times.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -46,40 +46,62 @@ void tm_init(p_tm tm, int block, int total)
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Set and get timeout limits * Determines how much time we have left for the next system call,
\*-------------------------------------------------------------------------*/ * if the previous call was successful
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
* Input * Input
* tm: timeout control structure * tm: timeout control structure
* Returns * Returns
* the number of ms left or -1 if there is no time limit * 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; return -1;
/* there is no block timeout, we use the return timeout */ } else if (tm->block < 0) {
else if (tm->block < 0) int t = tm->total - tm_gettime() + tm->start;
return MAX(tm->total - tm_gettime() + tm->start, 0); return MAX(t, 0);
/* there is no return timeout, we use the block timeout */ } else if (tm->total < 0) {
else if (tm->total < 0)
return tm->block; return tm->block;
/* both timeouts are specified */ } else {
else return MIN(tm->block, int t = tm->total - tm_gettime() + tm->start;
MAX(tm->total - tm_gettime() + tm->start, 0)); 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"); const char *mode = luaL_optstring(L, 3, "b");
switch (*mode) { switch (*mode) {
case 'b': case 'b':
tm_setblock(tm, ms); tm->block = ms;
break; break;
case 'r': case 't': case 'r': case 't':
tm_settotal(tm, ms); tm->total = ms;
break; break;
default: default:
luaL_argcheck(L, 0, 3, "invalid timeout mode"); 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_open(lua_State *L);
void tm_init(p_tm tm, int block, int total); void tm_init(p_tm tm, int block, int total);
void tm_setblock(p_tm tm, int block); int tm_getsuccess(p_tm tm);
void tm_settotal(p_tm tm, int total); int tm_getfailure(p_tm tm);
int tm_getblock(p_tm tm);
int tm_gettotal(p_tm tm);
void tm_markstart(p_tm tm); void tm_markstart(p_tm tm);
int tm_getstart(p_tm tm); int tm_getstart(p_tm tm);
int tm_get(p_tm tm);
int tm_gettime(void); int tm_gettime(void);
int tm_meth_settimeout(lua_State *L, p_tm tm); 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; int err;
const char *data = luaL_checklstring(L, 2, &count); const char *data = luaL_checklstring(L, 2, &count);
tm_markstart(tm); 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); if (err == IO_DONE) lua_pushnumber(L, sent);
else lua_pushnil(L); else lua_pushnil(L);
/* a 'closed' error on an unconnected means the target address was not /* 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); addr.sin_port = htons(port);
tm_markstart(tm); tm_markstart(tm);
err = sock_sendto(&udp->sock, data, count, &sent, 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); if (err == IO_DONE) lua_pushnumber(L, sent);
else lua_pushnil(L); else lua_pushnil(L);
/* a 'closed' error on an unconnected means the target address was not /* 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; p_tm tm = &udp->tm;
count = MIN(count, sizeof(buffer)); count = MIN(count, sizeof(buffer));
tm_markstart(tm); 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); if (err == IO_DONE) lua_pushlstring(L, buffer, got);
else lua_pushnil(L); else lua_pushnil(L);
io_pusherror(L, err); io_pusherror(L, err);
@ -172,7 +172,7 @@ static int meth_receivefrom(lua_State *L)
tm_markstart(tm); tm_markstart(tm);
count = MIN(count, sizeof(buffer)); count = MIN(count, sizeof(buffer));
err = sock_recvfrom(&udp->sock, buffer, count, &got, 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) { if (err == IO_DONE) {
lua_pushlstring(L, buffer, got); lua_pushlstring(L, buffer, got);
lua_pushstring(L, inet_ntoa(addr.sin_addr)); 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; SA dummy_addr;
socklen_t dummy_len; socklen_t dummy_len;
fd_set fds; fd_set fds;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(sock, &fds); FD_SET(sock, &fds);
*pa = SOCK_INVALID;
if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
return IO_TIMEOUT; return IO_TIMEOUT;
if (!addr) addr = &dummy_addr; 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; ssize_t put = 0;
int err; int err;
int ret; int ret;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); 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; ssize_t put = 0;
int err; int err;
int ret; int ret;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); 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; fd_set fds;
int ret; int ret;
ssize_t taken = 0; ssize_t taken = 0;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); FD_ZERO(&fds);
@ -210,6 +215,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
struct timeval tv; struct timeval tv;
fd_set fds; fd_set fds;
int ret; int ret;
if (sock == SOCK_INVALID) return IO_CLOSED;
ssize_t taken = 0; ssize_t taken = 0;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;

View File

@ -34,11 +34,6 @@
/* TCP options (nagle algorithm disable) */ /* TCP options (nagle algorithm disable) */
#include <netinet/tcp.h> #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 int t_sock;
typedef t_sock *p_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; SA dummy_addr;
socklen_t dummy_len; socklen_t dummy_len;
fd_set fds; fd_set fds;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(sock, &fds); FD_SET(sock, &fds);
*pa = SOCK_INVALID;
if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
return IO_TIMEOUT; return IO_TIMEOUT;
if (!addr) addr = &dummy_addr; 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; struct timeval tv;
fd_set fds; fd_set fds;
ssize_t put = 0; ssize_t put = 0;
if (sock == SOCK_INVALID) return IO_CLOSED;
int err; int err;
int ret; int ret;
tv.tv_sec = timeout / 1000; 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; ssize_t put = 0;
int err; int err;
int ret; int ret;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); 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; fd_set fds;
int ret; int ret;
ssize_t taken = 0; ssize_t taken = 0;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); FD_ZERO(&fds);
@ -214,6 +219,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
fd_set fds; fd_set fds;
int ret; int ret;
ssize_t taken = 0; ssize_t taken = 0;
if (sock == SOCK_INVALID) return IO_CLOSED;
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds); FD_ZERO(&fds);