diff --git a/TODO b/TODO
index bd8a950..5566d16 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,13 @@
-change send/recv to avoid using select
+
+
+check for interrupt compliance
+add connect with timeout
add gethostname and use it in HTTP, SMTP etc, and add manual entry.
+
add local connect, and manual entry
-add shutdown, and manual entry
+
+add shutdown manual entry
only allocate in case of success
only call select if io fails...
@@ -65,6 +70,8 @@ Ajeitar o protocolo da luaopen_socket()... sei l
- testar os options!
- adicionar exemplos de expansão: pipe, local, named pipe
+* add shutdown
+* change send/recv to avoid using select
* O location do "redirect" pode ser relativo ao servidor atual (não pode,
mas os servidores fazem merda...)
* Ajeitar para Lua 5.0
diff --git a/luasocket.sln b/luasocket.sln
new file mode 100644
index 0000000..25fe127
--- /dev/null
+++ b/luasocket.sln
@@ -0,0 +1,23 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luasocket", "luasocket.vcproj", "{4FAAB633-F0E7-4D12-B680-D150A0DD7268}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Debug.ActiveCfg = Debug|Win32
+ {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Debug.Build.0 = Debug|Win32
+ {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Release.ActiveCfg = Release|Win32
+ {4FAAB633-F0E7-4D12-B680-D150A0DD7268}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionItems) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/luasocket.vcproj b/luasocket.vcproj
new file mode 100644
index 0000000..b5c4d53
--- /dev/null
+++ b/luasocket.vcproj
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/inet.h b/src/inet.h
index 244a310..b69e82d 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -19,6 +19,10 @@
#include
#include "socket.h"
+#ifdef WIN32
+#define INET_ATON
+#endif
+
void inet_open(lua_State *L);
const char *inet_tryconnect(p_sock ps, const char *address,
unsigned short port);
diff --git a/src/luasocket.h b/src/luasocket.h
index 7756605..ac26824 100644
--- a/src/luasocket.h
+++ b/src/luasocket.h
@@ -18,7 +18,9 @@
/*-------------------------------------------------------------------------*\
* Library's namespace
\*-------------------------------------------------------------------------*/
+#ifndef LUASOCKET_LIBNAME
#define LUASOCKET_LIBNAME "socket"
+#endif
/*-------------------------------------------------------------------------*\
* This macro prefixes all exported API functions
diff --git a/src/tcp.c b/src/tcp.c
index afa0477..a67b44a 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -36,6 +36,7 @@ static int meth_dirty(lua_State *L);
static int opt_tcp_nodelay(lua_State *L);
static int opt_keepalive(lua_State *L);
static int opt_linger(lua_State *L);
+static int opt_reuseaddr(lua_State *L);
/* tcp object methods */
static luaL_reg tcp[] = {
@@ -61,6 +62,7 @@ static luaL_reg tcp[] = {
/* socket option handlers */
static luaL_reg opt[] = {
{"keepalive", opt_keepalive},
+ {"reuseaddr", opt_reuseaddr},
{"tcp-nodelay", opt_tcp_nodelay},
{"linger", opt_linger},
{NULL, NULL}
@@ -123,7 +125,7 @@ static int meth_setoption(lua_State *L)
static int opt_boolean(lua_State *L, int level, int name)
{
- p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1);
+ p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
int val = aux_checkboolean(L, 2);
if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
lua_pushnil(L);
@@ -134,16 +136,16 @@ static int opt_boolean(lua_State *L, int level, int name)
return 1;
}
+/* enables reuse of local address */
+static int opt_reuseaddr(lua_State *L)
+{
+ return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR);
+}
+
/* disables the Naggle algorithm */
static int opt_tcp_nodelay(lua_State *L)
{
- struct protoent *pe = getprotobyname("TCP");
- if (!pe) {
- lua_pushnil(L);
- lua_pushstring(L, "getprotobyname");
- return 2;
- }
- return opt_boolean(L, pe->p_proto, TCP_NODELAY);
+ return opt_boolean(L, IPPROTO_TCP, TCP_NODELAY);
}
static int opt_keepalive(lua_State *L)
diff --git a/src/timeout.c b/src/timeout.c
index 5d6de99..2d88ded 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -16,6 +16,7 @@
#ifdef WIN32
#include
#else
+#include
#include
#include
#include
diff --git a/src/udp.c b/src/udp.c
index 58119cd..21730ab 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -35,6 +35,11 @@ static int meth_fd(lua_State *L);
static int meth_dirty(lua_State *L);
static int opt_dontroute(lua_State *L);
static int opt_broadcast(lua_State *L);
+static int opt_reuseaddr(lua_State *L);
+static int opt_ip_multicast_ttl(lua_State *L);
+static int opt_ip_multicast_loop(lua_State *L);
+static int opt_ip_add_membership(lua_State *L);
+static int opt_ip_drop_membersip(lua_State *L);
/* udp object methods */
static luaL_reg udp[] = {
@@ -57,8 +62,13 @@ static luaL_reg udp[] = {
/* socket options */
static luaL_reg opt[] = {
- {"dontroute", opt_dontroute},
- {"broadcast", opt_broadcast},
+ {"dontroute", opt_dontroute},
+ {"broadcast", opt_broadcast},
+ {"reuseaddr", opt_reuseaddr},
+ {"ip-multicast-ttl", opt_ip_multicast_ttl},
+ {"ip-multicast-loop", opt_ip_multicast_loop},
+ {"ip-add-membership", opt_ip_add_membership},
+ {"ip-drop-membership", opt_ip_drop_membersip},
{NULL, NULL}
};
@@ -244,11 +254,72 @@ static int opt_dontroute(lua_State *L)
return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE);
}
+static int opt_reuseaddr(lua_State *L)
+{
+ return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR);
+}
+
static int opt_broadcast(lua_State *L)
{
return opt_boolean(L, SOL_SOCKET, SO_BROADCAST);
}
+static int opt_ip_multicast_loop(lua_State *L)
+{
+ return opt_boolean(L, IPPROTO_IP, IP_MULTICAST_LOOP);
+}
+
+static int opt_ip_multicast_ttl(lua_State *L)
+{
+ p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
+ int val = (int) luaL_checknumber(L, 2);
+ if (setsockopt(udp->sock, IPPROTO_IP, IP_MULTICAST_TTL,
+ (char *) &val, sizeof(val)) < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, "setsockopt failed");
+ return 2;
+ }
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+static int opt_membership(lua_State *L, int level, int name)
+{
+ p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
+ struct ip_mreq val;
+ if (!lua_istable(L, 2))
+ luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE));
+ lua_pushstring(L, "multiaddr");
+ lua_gettable(L, 2);
+ if (!lua_isstring(L, -1)) luaL_argerror(L, 2, "invalid 'group' field");
+ if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr))
+ luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
+ lua_pushstring(L, "interface");
+ lua_gettable(L, 2);
+ if (!lua_isstring(L, -1)) luaL_argerror(L, 2, "invalid 'interface' field");
+ val.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (strcmp(lua_tostring(L, -1), "*") &&
+ !inet_aton(lua_tostring(L, -1), &val.imr_interface))
+ luaL_argerror(L, 3, "invalid 'interface' ip address");
+ if (setsockopt(udp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, "setsockopt failed");
+ return 2;
+ }
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+static int opt_ip_add_membership(lua_State *L)
+{
+ return opt_membership(L, IPPROTO_IP, IP_ADD_MEMBERSHIP);
+}
+
+static int opt_ip_drop_membersip(lua_State *L)
+{
+ return opt_membership(L, IPPROTO_IP, IP_DROP_MEMBERSHIP);
+}
+
/*-------------------------------------------------------------------------*\
* Just call tm methods
\*-------------------------------------------------------------------------*/
diff --git a/src/usocket.c b/src/usocket.c
index f2d9f01..89be85e 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -145,7 +145,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
else return IO_TIMEOUT;
/* here we know the connection has been closed */
} else return IO_CLOSED;
- /* here we sent successfully sent something */
+ /* here we successfully sent something */
} else {
*sent = put;
return IO_DONE;
@@ -159,34 +159,36 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
SA *addr, socklen_t addr_len, int timeout)
{
t_sock sock = *ps;
- struct timeval tv;
- fd_set fds;
- ssize_t put = 0;
- int err;
+ ssize_t put;
int ret;
+ /* avoid making system calls on closed sockets */
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);
- ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
- if (ret > 0) {
- put = sendto(sock, data, count, 0, addr, addr_len);
- if (put <= 0) {
- err = IO_CLOSED;
-#ifdef __CYGWIN__
- /* this is for CYGWIN, which is like Unix but has Win32 bugs */
- if (sent < 0 && errno == EWOULDBLOCK) err = IO_DONE;
-#endif
- *sent = 0;
- } else {
- *sent = put;
- err = IO_DONE;
- }
- return err;
- } else {
+ /* make sure we repeat in case the call was interrupted */
+ do put = sendto(sock, data, count, 0, addr, addr_len);
+ while (put <= 0 && errno == EINTR);
+ /* deal with failure */
+ if (put <= 0) {
+ /* in any case, nothing has been sent */
*sent = 0;
- return IO_TIMEOUT;
+ /* run select to avoid busy wait */
+ if (errno != EPIPE) {
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
+ /* tell the caller to call us again because there is more data */
+ if (ret > 0) return IO_DONE;
+ /* tell the caller there was no data before timeout */
+ else return IO_TIMEOUT;
+ /* here we know the connection has been closed */
+ } else return IO_CLOSED;
+ /* here we successfully sent something */
+ } else {
+ *sent = put;
+ return IO_DONE;
}
}
@@ -232,28 +234,26 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
SA *addr, socklen_t *addr_len, int timeout)
{
t_sock sock = *ps;
- struct timeval tv;
- fd_set fds;
- int ret;
+ ssize_t taken;
if (sock == SOCK_INVALID) return IO_CLOSED;
- ssize_t taken = 0;
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- FD_ZERO(&fds);
- FD_SET(sock, &fds);
- ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
- if (ret > 0) {
- taken = recvfrom(sock, data, count, 0, addr, addr_len);
- if (taken <= 0) {
- *got = 0;
- return IO_CLOSED;
- } else {
- *got = taken;
- return IO_DONE;
- }
- } else {
+ do taken = recvfrom(sock, data, count, 0, addr, addr_len);
+ while (taken <= 0 && errno == EINTR);
+ if (taken <= 0) {
+ struct timeval tv;
+ fd_set fds;
+ int ret;
*got = 0;
- return IO_TIMEOUT;
+ if (taken == 0) return IO_CLOSED;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
+ if (ret > 0) return IO_DONE;
+ else return IO_TIMEOUT;
+ } else {
+ *got = taken;
+ return IO_DONE;
}
}
diff --git a/src/wsocket.c b/src/wsocket.c
index 59d88df..30208b9 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -100,7 +100,7 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
FD_ZERO(&fds);
FD_SET(sock, &fds);
*pa = SOCK_INVALID;
- if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
+ if (select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
return IO_TIMEOUT;
if (!addr) addr = &dummy_addr;
if (!addr_len) addr_len = &dummy_len;
@@ -116,34 +116,35 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
int timeout)
{
t_sock sock = *ps;
- struct timeval tv;
- fd_set fds;
- ssize_t put = 0;
- if (sock == SOCK_INVALID) return IO_CLOSED;
- int err;
+ ssize_t put;
int ret;
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- FD_ZERO(&fds);
- FD_SET(sock, &fds);
- ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
- if (ret > 0) {
- put = send(sock, data, count, 0);
- if (put <= 0) {
- /* a bug in WinSock forces us to do a busy wait until we manage
- ** to write, because select returns immediately even though it
- ** should have blocked us until we could write... */
- if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE;
- else err = IO_CLOSED;
- *sent = 0;
- } else {
- *sent = put;
- err = IO_DONE;
- }
- return err;
- } else {
+ /* avoid making system calls on closed sockets */
+ if (sock == SOCK_INVALID) return IO_CLOSED;
+ /* try to send something */
+ put = send(sock, data, (int) count, 0);
+ /* deal with failure */
+ if (put <= 0) {
+ /* in any case, nothing has been sent */
*sent = 0;
- return IO_TIMEOUT;
+ /* run select to avoid busy wait */
+ if (WSAGetLastError() == WSAEWOULDBLOCK) {
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
+ /* tell the caller to call us again because there is more data */
+ if (ret > 0) return IO_DONE;
+ /* tell the caller there was no data before timeout */
+ else return IO_TIMEOUT;
+ /* here we know the connection has been closed */
+ } else return IO_CLOSED;
+ /* here we successfully sent something */
+ } else {
+ *sent = put;
+ return IO_DONE;
}
}
@@ -154,34 +155,35 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
SA *addr, socklen_t addr_len, int timeout)
{
t_sock sock = *ps;
- struct timeval tv;
- fd_set fds;
- ssize_t put = 0;
- int err;
+ ssize_t put;
int ret;
+ /* avoid making system calls on closed sockets */
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);
- ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
- if (ret > 0) {
- put = sendto(sock, data, count, 0, addr, addr_len);
- if (put <= 0) {
- /* a bug in WinSock forces us to do a busy wait until we manage
- ** to write, because select returns immediately even though it
- ** should have blocked us until we could write... */
- if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE;
- else err = IO_CLOSED;
- *sent = 0;
- } else {
- *sent = put;
- err = IO_DONE;
- }
- return err;
- } else {
+ /* try to send something */
+ put = sendto(sock, data, (int) count, 0, addr, addr_len);
+ /* deal with failure */
+ if (put <= 0) {
+ /* in any case, nothing has been sent */
*sent = 0;
- return IO_TIMEOUT;
+ /* run select to avoid busy wait */
+ if (WSAGetLastError() == WSAEWOULDBLOCK) {
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL);
+ /* tell the caller to call us again because there is more data */
+ if (ret > 0) return IO_DONE;
+ /* tell the caller there was no data before timeout */
+ else return IO_TIMEOUT;
+ /* here we know the connection has been closed */
+ } else return IO_CLOSED;
+ /* here we successfully sent something */
+ } else {
+ *sent = put;
+ return IO_DONE;
}
}
@@ -191,28 +193,25 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
{
t_sock sock = *ps;
- struct timeval tv;
- fd_set fds;
- int ret;
- ssize_t taken = 0;
+ ssize_t taken;
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);
- ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
- if (ret > 0) {
- taken = recv(sock, data, count, 0);
- if (taken <= 0) {
- *got = 0;
- return IO_CLOSED;
- } else {
- *got = taken;
- return IO_DONE;
- }
- } else {
+ taken = recv(sock, data, (int) count, 0);
+ if (taken <= 0) {
+ struct timeval tv;
+ fd_set fds;
+ int ret;
*got = 0;
- return IO_TIMEOUT;
+ if (taken == 0) return IO_CLOSED;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
+ if (ret > 0) return IO_DONE;
+ else return IO_TIMEOUT;
+ } else {
+ *got = taken;
+ return IO_DONE;
}
}
@@ -223,28 +222,25 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
SA *addr, socklen_t *addr_len, int timeout)
{
t_sock sock = *ps;
- struct timeval tv;
- fd_set fds;
- int ret;
- ssize_t taken = 0;
+ ssize_t taken;
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);
- ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
- if (ret > 0) {
- taken = recvfrom(sock, data, count, 0, addr, addr_len);
- if (taken <= 0) {
- *got = 0;
- return IO_CLOSED;
- } else {
- *got = taken;
- return IO_DONE;
- }
- } else {
+ taken = recvfrom(sock, data, (int) count, 0, addr, addr_len);
+ if (taken <= 0) {
+ struct timeval tv;
+ fd_set fds;
+ int ret;
*got = 0;
- return IO_TIMEOUT;
+ if (taken == 0) return IO_CLOSED;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
+ if (ret > 0) return IO_DONE;
+ else return IO_TIMEOUT;
+ } else {
+ *got = taken;
+ return IO_DONE;
}
}
diff --git a/test/testclnt.lua b/test/testclnt.lua
index 2420711..6b07dca 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -99,8 +99,6 @@ else pass("connected!") end
control:setoption("tcp-nodelay", true)
------------------------------------------------------------------------
-test("method registration")
-
function test_methods(sock, methods)
for _, v in methods do
if type(sock[v]) ~= "function" then
@@ -110,38 +108,7 @@ function test_methods(sock, methods)
pass(sock.class .. " methods are ok")
end
-test_methods(socket.tcp(), {
- "connect",
- "send",
- "receive",
- "bind",
- "accept",
- "setpeername",
- "setsockname",
- "getpeername",
- "getsockname",
- "setoption",
- "settimeout",
- "close",
-})
-
-test_methods(socket.udp(), {
- "getpeername",
- "getsockname",
- "setsockname",
- "setpeername",
- "send",
- "sendto",
- "receive",
- "receivefrom",
- "setoption",
- "settimeout",
- "close",
-})
-
------------------------------------------------------------------------
-test("mixed patterns")
-
function test_mixed(len)
reconnect()
local inter = math.ceil(len/4)
@@ -163,21 +130,7 @@ remote "data:send(str); data:close()"
else fail("patterns don't match") end
end
-
-test_mixed(1)
-test_mixed(17)
-test_mixed(200)
-test_mixed(4091)
-test_mixed(80199)
-test_mixed(4091)
-test_mixed(200)
-test_mixed(17)
-test_mixed(1)
-
------------------------------------------------------------------------
-test("character line")
-reconnect()
-
function test_asciiline(len)
local str, str10, back, err
str = string.rep("x", math.mod(len, 10))
@@ -194,22 +147,7 @@ remote "data:send(str, '\\n')"
else fail("lines don't match") end
end
-test_asciiline(1)
-test_asciiline(17)
-test_asciiline(200)
-test_asciiline(4091)
-test_asciiline(80199)
-test_asciiline(800000)
-test_asciiline(80199)
-test_asciiline(4091)
-test_asciiline(200)
-test_asciiline(17)
-test_asciiline(1)
-
------------------------------------------------------------------------
-test("binary line")
-reconnect()
-
function test_rawline(len)
local str, str10, back, err
str = string.rep(string.char(47), math.mod(len, 10))
@@ -227,22 +165,7 @@ remote "data:send(str, '\\n')"
else fail("lines don't match") end
end
-test_rawline(1)
-test_rawline(17)
-test_rawline(200)
-test_rawline(4091)
-test_rawline(80199)
-test_rawline(800000)
-test_rawline(80199)
-test_rawline(4091)
-test_rawline(200)
-test_rawline(17)
-test_rawline(1)
-
------------------------------------------------------------------------
-test("raw transfer")
-reconnect()
-
function test_raw(len)
local half = math.floor(len/2)
local s1, s2, back, err
@@ -261,38 +184,7 @@ remote "data:send(str)"
else fail("blocks don't match") end
end
-test_raw(1)
-test_raw(17)
-test_raw(200)
-test_raw(4091)
-test_raw(80199)
-test_raw(800000)
-test_raw(80199)
-test_raw(4091)
-test_raw(200)
-test_raw(17)
-test_raw(1)
------------------------------------------------------------------------
-test("non-blocking transfer")
-reconnect()
-
--- the value is not important, we only want
--- to test non-blockin I/O anyways
-data:settimeout(200)
-test_raw(1)
-test_raw(17)
-test_raw(200)
-test_raw(4091)
-test_raw(80199)
-test_raw(800000)
-test_raw(80199)
-test_raw(4091)
-test_raw(200)
-test_raw(17)
-test_raw(1)
-
-------------------------------------------------------------------------
-test("total timeout on receive")
function test_totaltimeoutreceive(len, tm, sl)
local str, err, total
reconnect()
@@ -311,13 +203,8 @@ function test_totaltimeoutreceive(len, tm, sl)
check_timeout(tm, sl, elapsed, err, "receive", "total",
string.len(str) == 2*len)
end
-test_totaltimeoutreceive(800091, 1, 3)
-test_totaltimeoutreceive(800091, 2, 3)
-test_totaltimeoutreceive(800091, 3, 2)
-test_totaltimeoutreceive(800091, 3, 1)
------------------------------------------------------------------------
-test("total timeout on send")
function test_totaltimeoutsend(len, tm, sl)
local str, err, total
reconnect()
@@ -336,13 +223,8 @@ function test_totaltimeoutsend(len, tm, sl)
check_timeout(tm, sl, elapsed, err, "send", "total",
total == 2*len)
end
-test_totaltimeoutsend(800091, 1, 3)
-test_totaltimeoutsend(800091, 2, 3)
-test_totaltimeoutsend(800091, 3, 2)
-test_totaltimeoutsend(800091, 3, 1)
------------------------------------------------------------------------
-test("blocking timeout on receive")
function test_blockingtimeoutreceive(len, tm, sl)
local str, err, total
reconnect()
@@ -361,13 +243,8 @@ function test_blockingtimeoutreceive(len, tm, sl)
check_timeout(tm, sl, elapsed, err, "receive", "blocking",
string.len(str) == 2*len)
end
-test_blockingtimeoutreceive(800091, 1, 3)
-test_blockingtimeoutreceive(800091, 2, 3)
-test_blockingtimeoutreceive(800091, 3, 2)
-test_blockingtimeoutreceive(800091, 3, 1)
------------------------------------------------------------------------
-test("blocking timeout on send")
function test_blockingtimeoutsend(len, tm, sl)
local str, err, total
reconnect()
@@ -386,15 +263,8 @@ function test_blockingtimeoutsend(len, tm, sl)
check_timeout(tm, sl, elapsed, err, "send", "blocking",
total == 2*len)
end
-test_blockingtimeoutsend(800091, 1, 3)
-test_blockingtimeoutsend(800091, 2, 3)
-test_blockingtimeoutsend(800091, 3, 2)
-test_blockingtimeoutsend(800091, 3, 1)
------------------------------------------------------------------------
-test("bugs")
-
-io.write("empty host connect: ")
function empty_connect()
if data then data:close() data = nil end
remote [[
@@ -408,27 +278,25 @@ function empty_connect()
else fail("should not have connected!") end
end
-empty_connect()
+------------------------------------------------------------------------
+function isclosed(c)
+ return c:fd() == -1 or c:fd() == (2^32-1)
+end
--- io.write("active close: ")
function active_close()
reconnect()
- if socket._isclosed(data) then fail("should not be closed") end
+ if isclosed(data) then fail("should not be closed") end
data:close()
- if not socket._isclosed(data) then fail("should be closed") end
+ if not isclosed(data) then fail("should be closed") end
data = nil
local udp = socket.udp()
- if socket._isclosed(udp) then fail("should not be closed") end
+ if isclosed(udp) then fail("should not be closed") end
udp:close()
- if not socket._isclosed(udp) then fail("should be closed") end
+ if not isclosed(udp) then fail("should be closed") end
pass("ok")
end
--- active_close()
-
------------------------------------------------------------------------
-test("closed connection detection")
-
function test_closed()
local back, err
local str = 'little string'
@@ -453,18 +321,15 @@ function test_closed()
]]
total, err = data:send(string.rep("ugauga", 100000))
if not err then
-pass("failed: output buffer is at least %d bytes long!", total)
+ pass("failed: output buffer is at least %d bytes long!", total)
elseif err ~= "closed" then
-fail("got '"..err.."' instead of 'closed'.")
+ fail("got '"..err.."' instead of 'closed'.")
else
-pass("graceful 'closed' received after %d bytes were sent", total)
+ pass("graceful 'closed' received after %d bytes were sent", total)
end
end
-test_closed()
-
------------------------------------------------------------------------
-test("select function")
function test_selectbugs()
local r, s, e = socket.select(nil, nil, 0.1)
assert(type(r) == "table" and type(s) == "table" and e == "timeout")
@@ -481,7 +346,144 @@ function test_selectbugs()
pass("invalid input: ok")
end
+test("method registration")
+test_methods(socket.tcp(), {
+ "connect",
+ "send",
+ "receive",
+ "bind",
+ "accept",
+ "setpeername",
+ "setsockname",
+ "getpeername",
+ "getsockname",
+ "setoption",
+ "settimeout",
+ "close",
+})
+test_methods(socket.udp(), {
+ "getpeername",
+ "getsockname",
+ "setsockname",
+ "setpeername",
+ "send",
+ "sendto",
+ "receive",
+ "receivefrom",
+ "setoption",
+ "settimeout",
+ "close",
+})
+
+test("mixed patterns")
+reconnect()
+test_mixed(1)
+test_mixed(17)
+test_mixed(200)
+test_mixed(4091)
+test_mixed(801990)
+test_mixed(4091)
+test_mixed(200)
+test_mixed(17)
+test_mixed(1)
+
+test("character line")
+reconnect()
+test_asciiline(1)
+test_asciiline(17)
+test_asciiline(200)
+test_asciiline(4091)
+test_asciiline(80199)
+test_asciiline(8000000)
+test_asciiline(80199)
+test_asciiline(4091)
+test_asciiline(200)
+test_asciiline(17)
+test_asciiline(1)
+
+test("binary line")
+reconnect()
+test_rawline(1)
+test_rawline(17)
+test_rawline(200)
+test_rawline(4091)
+test_rawline(80199)
+test_rawline(8000000)
+test_rawline(80199)
+test_rawline(4091)
+test_rawline(200)
+test_rawline(17)
+test_rawline(1)
+
+test("raw transfer")
+reconnect()
+test_raw(1)
+test_raw(17)
+test_raw(200)
+test_raw(4091)
+test_raw(80199)
+test_raw(8000000)
+test_raw(80199)
+test_raw(4091)
+test_raw(200)
+test_raw(17)
+test_raw(1)
+
+test("non-blocking transfer")
+reconnect()
+-- the value is not important, we only want
+-- to test non-blockin I/O anyways
+data:settimeout(200)
+test_raw(1)
+test_raw(17)
+test_raw(200)
+test_raw(4091)
+test_raw(80199)
+test_raw(8000000)
+test_raw(80199)
+test_raw(4091)
+test_raw(200)
+test_raw(17)
+test_raw(1)
+
+test("select function")
test_selectbugs()
+test("empty host connect: ")
+empty_connect()
+
+test("active close: ")
+active_close()
+
+test("closed connection detection: ")
+test_closed()
+
+a = [[
+test("total timeout on send")
+test_totaltimeoutsend(800091, 1, 3)
+test_totaltimeoutsend(800091, 2, 3)
+test_totaltimeoutsend(800091, 3, 2)
+test_totaltimeoutsend(800091, 3, 1)
+
+test("total timeout on receive")
+test_totaltimeoutreceive(800091, 1, 3)
+test_totaltimeoutreceive(800091, 2, 3)
+test_totaltimeoutreceive(800091, 3, 2)
+test_totaltimeoutreceive(800091, 3, 1)
+
+test("blocking timeout on send")
+test_blockingtimeoutsend(800091, 1, 3)
+test_blockingtimeoutsend(800091, 2, 3)
+test_blockingtimeoutsend(800091, 3, 2)
+test_blockingtimeoutsend(800091, 3, 1)
+
+test("blocking timeout on receive")
+test_blockingtimeoutreceive(800091, 1, 3)
+test_blockingtimeoutreceive(800091, 2, 3)
+test_blockingtimeoutreceive(800091, 3, 2)
+test_blockingtimeoutreceive(800091, 3, 1)
+]]
+
+socket.done()
test(string.format("done in %.2fs", socket.time() - start))