diff --git a/config b/config index 5a86f9c..6fd1646 100644 --- a/config +++ b/config @@ -6,8 +6,8 @@ # Output file names # EXT=so -SOCKET_V=2.0.1 -MIME_V=1.0.1 +SOCKET_V=2.0.2 +MIME_V=1.0.2 SOCKET_SO=socket.$(EXT).$(SOCKET_V) MIME_SO=mime.$(EXT).$(MIME_V) UNIX_SO=unix.$(EXT) @@ -41,7 +41,7 @@ INSTALL_EXEC=cp # for Mac OS X # CC=gcc -DEF=-DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN +DEF= -DAAA -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common LDFLAGS=-bundle -undefined dynamic_lookup LD=export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc diff --git a/doc/socket.html b/doc/socket.html index 16a025b..f096e4b 100644 --- a/doc/socket.html +++ b/doc/socket.html @@ -190,11 +190,13 @@ be empty tables or nil. Non-socket values (or values with non-numeric indices) in the arrays will be silently ignored.

-

The function returns a table with the sockets ready for -reading, a table with the sockets ready for writing and an error message. +

The function returns a list with the sockets ready for +reading, a list with the sockets ready for writing and an error message. The error message is "timeout" if a timeout condition was met and -nil otherwise. The returned tables are associative, to -simplify the test if a specific socket has changed status. +nil otherwise. The returned tables are +doubly keyed both by integers and also by the sockets +themselves, to simplify the test if a specific socket has +changed status.

diff --git a/etc/dispatch.lua b/etc/dispatch.lua index 6f3855e..3ef1e72 100644 --- a/etc/dispatch.lua +++ b/etc/dispatch.lua @@ -56,7 +56,7 @@ function socket.protect(f) if not status then if type(results[1]) == 'table' then return nil, results[1][1] - else error(results[1]) end + else base.error(results[1]) end end if coroutine.status(co) == "suspended" then arg = {coroutine.yield(base.unpack(results))} @@ -219,7 +219,7 @@ function schedule(cortn, status, operation, tcp) operation.cortn[tcp] = cortn operation.stamp[tcp] = socket.gettime() end - else error(operation) end + else base.error(operation) end end function kick(operation, tcp) diff --git a/makefile.dist b/makefile.dist index e3b0e5c..58ae5b3 100644 --- a/makefile.dist +++ b/makefile.dist @@ -1,9 +1,7 @@ #-------------------------------------------------------------------------- # Distribution makefile #-------------------------------------------------------------------------- -DIST = luasocket-2.0.1 - -COMPAT = src/compat-5.1r5 +DIST = luasocket-2.0.2 TEST = \ test/README \ @@ -115,7 +113,6 @@ dist: mkdir -p $(DIST)/src cp -vf $(SRC) $(DIST)/src - cp -vfr $(COMPAT) $(DIST)/src mkdir -p $(DIST)/doc cp -vf $(DOC) $(DIST)/doc diff --git a/src/buffer.c b/src/buffer.c index df1a0bc..de817b2 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -75,12 +75,12 @@ int buffer_meth_setstats(lua_State *L, p_buffer buf) { \*-------------------------------------------------------------------------*/ int buffer_meth_send(lua_State *L, p_buffer buf) { int top = lua_gettop(L); - p_timeout tm = timeout_markstart(buf->tm); int err = IO_DONE; size_t size = 0, sent = 0; const char *data = luaL_checklstring(L, 2, &size); long start = (long) luaL_optnumber(L, 3, 1); long end = (long) luaL_optnumber(L, 4, -1); + p_timeout tm = timeout_markstart(buf->tm); if (start < 0) start = (long) (size+start+1); if (end < 0) end = (long) (size+end+1); if (start < 1) start = (long) 1; @@ -108,10 +108,10 @@ int buffer_meth_send(lua_State *L, p_buffer buf) { \*-------------------------------------------------------------------------*/ int buffer_meth_receive(lua_State *L, p_buffer buf) { int err = IO_DONE, top = lua_gettop(L); - p_timeout tm = timeout_markstart(buf->tm); luaL_Buffer b; size_t size; const char *part = luaL_optlstring(L, 3, "", &size); + p_timeout tm = timeout_markstart(buf->tm); /* initialize buffer with optional extra prefix * (useful for concatenating previous partial results) */ luaL_buffinit(L, &b); @@ -182,13 +182,14 @@ static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) { static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) { int err = IO_DONE; size_t total = 0; - while (total < wanted && err == IO_DONE) { + while (err == IO_DONE) { size_t count; const char *data; err = buffer_get(buf, &data, &count); count = MIN(count, wanted - total); luaL_addlstring(b, data, count); buffer_skip(buf, count); total += count; + if (total >= wanted) break; } return err; } @@ -198,14 +199,18 @@ static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) { \*-------------------------------------------------------------------------*/ static int recvall(p_buffer buf, luaL_Buffer *b) { int err = IO_DONE; + size_t total = 0; while (err == IO_DONE) { const char *data; size_t count; err = buffer_get(buf, &data, &count); + total += count; luaL_addlstring(b, data, count); buffer_skip(buf, count); } - if (err == IO_CLOSED) return IO_DONE; - else return err; + if (err == IO_CLOSED) { + if (total > 0) return IO_DONE; + else return IO_CLOSED; + } else return err; } /*-------------------------------------------------------------------------*\ diff --git a/src/luasocket.h b/src/luasocket.h index 46b5d06..13134cf 100644 --- a/src/luasocket.h +++ b/src/luasocket.h @@ -13,8 +13,8 @@ /*-------------------------------------------------------------------------*\ * Current socket library version \*-------------------------------------------------------------------------*/ -#define LUASOCKET_VERSION "LuaSocket 2.0.1" -#define LUASOCKET_COPYRIGHT "Copyright (C) 2004-2006 Diego Nehab" +#define LUASOCKET_VERSION "LuaSocket 2.0.2" +#define LUASOCKET_COPYRIGHT "Copyright (C) 2004-2007 Diego Nehab" #define LUASOCKET_AUTHORS "Diego Nehab" /*-------------------------------------------------------------------------*\ diff --git a/src/mime.h b/src/mime.h index 166cf5b..0fe8000 100644 --- a/src/mime.h +++ b/src/mime.h @@ -15,8 +15,8 @@ /*-------------------------------------------------------------------------*\ * Current MIME library version \*-------------------------------------------------------------------------*/ -#define MIME_VERSION "MIME 1.0.1" -#define MIME_COPYRIGHT "Copyright (C) 2004-2006 Diego Nehab" +#define MIME_VERSION "MIME 1.0.2" +#define MIME_COPYRIGHT "Copyright (C) 2004-2007 Diego Nehab" #define MIME_AUTHORS "Diego Nehab" /*-------------------------------------------------------------------------*\ diff --git a/src/mime.lua b/src/mime.lua index 3182545..eb75db2 100644 --- a/src/mime.lua +++ b/src/mime.lua @@ -27,7 +27,8 @@ local function choose(table) name, opt1, opt2 = "default", name, opt1 end local f = table[name or "nil"] - if not f then error("unknown key (" .. base.tostring(name) .. ")", 3) + if not f then + base.error("unknown key (" .. base.tostring(name) .. ")", 3) else return f(opt1, opt2) end end end diff --git a/src/usocket.c b/src/usocket.c index e70806a..ef275b4 100644 --- a/src/usocket.c +++ b/src/usocket.c @@ -206,10 +206,10 @@ int socket_send(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm) { int err; + *sent = 0; /* avoid making system calls on closed sockets */ if (*ps == SOCKET_INVALID) return IO_CLOSED; /* loop until we send something or we give up on error */ - *sent = 0; for ( ;; ) { long put = (long) send(*ps, data, count, 0); /* if we sent anything, we are done */ @@ -239,8 +239,8 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, SA *addr, socklen_t len, p_timeout tm) { int err; - if (*ps == SOCKET_INVALID) return IO_CLOSED; *sent = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { long put = (long) sendto(*ps, data, count, 0, addr, len); if (put > 0) { @@ -261,6 +261,7 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, \*-------------------------------------------------------------------------*/ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { int err; + *got = 0; if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { long taken = (long) recv(*ps, data, count, 0); @@ -269,7 +270,6 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm return IO_DONE; } err = errno; - *got = 0; if (taken == 0) return IO_CLOSED; if (err == EINTR) continue; if (err != EAGAIN) return err; @@ -284,6 +284,7 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, SA *addr, socklen_t *len, p_timeout tm) { int err; + *got = 0; if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { long taken = (long) recvfrom(*ps, data, count, 0, addr, len); @@ -292,7 +293,6 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, return IO_DONE; } err = errno; - *got = 0; if (taken == 0) return IO_CLOSED; if (err == EINTR) continue; if (err != EAGAIN) return err; diff --git a/src/wsocket.c b/src/wsocket.c index dce333b..e247777 100644 --- a/src/wsocket.c +++ b/src/wsocket.c @@ -201,10 +201,10 @@ int socket_send(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm) { int err; + *sent = 0; /* avoid making system calls on closed sockets */ if (*ps == SOCKET_INVALID) return IO_CLOSED; /* loop until we send something or we give up on error */ - *sent = 0; for ( ;; ) { /* try to send something */ int put = send(*ps, data, (int) count, 0); @@ -231,8 +231,8 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, SA *addr, socklen_t len, p_timeout tm) { int err; - if (*ps == SOCKET_INVALID) return IO_CLOSED; *sent = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { int put = sendto(*ps, data, (int) count, 0, addr, len); if (put > 0) { @@ -251,8 +251,8 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, \*-------------------------------------------------------------------------*/ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { int err; - if (*ps == SOCKET_INVALID) return IO_CLOSED; *got = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { int taken = recv(*ps, data, (int) count, 0); if (taken > 0) { @@ -273,8 +273,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, SA *addr, socklen_t *len, p_timeout tm) { int err; - if (*ps == SOCKET_INVALID) return IO_CLOSED; *got = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { int taken = recvfrom(*ps, data, (int) count, 0, addr, len); if (taken > 0) { diff --git a/test/testclnt.lua b/test/testclnt.lua index 304cfd3..2f4ffad 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua @@ -498,7 +498,63 @@ remote(string.format([[ end ------------------------------------------------------------------------ - +function test_readafterclose() + local back, partial, err + local str = 'little string' + reconnect() + pass("trying repeated '*a' pattern") + remote (string.format ([[ + data:send('%s') + data:close() + data = nil + ]], str)) + back, err, partial = data:receive("*a") + assert(back == str, "unexpected data read") + back, err, partial = data:receive("*a") + assert(back == nil and err == "closed", "should have returned 'closed'") + print("ok") + reconnect() + pass("trying active close before '*a'") + remote (string.format ([[ + data:close() + data = nil + ]])) + data:close() + back, err, partial = data:receive("*a") + assert(back == nil and err == "closed", "should have returned 'closed'") + print("ok") + reconnect() + pass("trying active close before '*l'") + remote (string.format ([[ + data:close() + data = nil + ]])) + data:close() + back, err, partial = data:receive() + assert(back == nil and err == "closed", "should have returned 'closed'") + print("ok") + reconnect() + pass("trying active close before raw 1") + remote (string.format ([[ + data:close() + data = nil + ]])) + data:close() + back, err, partial = data:receive(1) + assert(back == nil and err == "closed", "should have returned 'closed'") + print("ok") + reconnect() + pass("trying active close before raw 0") + remote (string.format ([[ + data:close() + data = nil + ]])) + data:close() + back, err, partial = data:receive(0) + assert(back == nil and err == "closed", "should have returned 'closed'") + print("ok") +os.exit() +end test("method registration") test_methods(socket.tcp(), { @@ -541,6 +597,9 @@ test_methods(socket.udp(), { "settimeout" }) +test("testing read after close") +test_readafterclose() + test("select function") test_selectbugs() diff --git a/test/testmesg.lua b/test/testmesg.lua index 04305f4..580693b 100644 --- a/test/testmesg.lua +++ b/test/testmesg.lua @@ -62,7 +62,7 @@ source = smtp.message{ headers = { ["ConTenT-tYpE"] = 'image/png; name="luasocket.png"', ["content-disposition"] = 'attachment; filename="luasocket.png"', - ["content-description"] = 'a beautiful image', + ["content-description"] = 'our logo', ["content-transfer-encoding"] = "BASE64" }, body = ltn12.source.chain(