From 96965b179c7311f850f72a8629b9ba6d3a31d117 Mon Sep 17 00:00:00 2001
From: Diego Nehab
Date: Sat, 22 Aug 2015 19:52:01 -0300
Subject: New agnostic IPv4 IPv6 functions.
Also dealing with EPROTOTYPE Yosemite seems to be throwing
at us for no reason.
---
test/testclnt.lua | 100 ++++++++++++++++++++++++------------------------
test/testsrvr.lua | 2 +-
test/udpconnectclnt.lua | 2 +-
3 files changed, 51 insertions(+), 53 deletions(-)
(limited to 'test')
diff --git a/test/testclnt.lua b/test/testclnt.lua
index 0014781..abf9608 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -8,7 +8,7 @@ function printf(...)
end
function pass(...)
- printf(...)
+ printf(...)
io.stderr:write("\n")
end
@@ -45,30 +45,30 @@ function check_timeout(tm, sl, elapsed, err, opp, mode, alldone)
if not err then warn("must be buffered")
elseif err == "timeout" then pass("proper timeout")
else fail("unexpected error '%s'", err) end
- else
- if err ~= "timeout" then fail("should have timed out")
+ else
+ if err ~= "timeout" then fail("should have timed out")
else pass("proper timeout") end
end
else
if mode == "total" then
- if elapsed > tm then
+ if elapsed > tm then
if err ~= "timeout" then fail("should have timed out")
else pass("proper timeout") end
elseif elapsed < tm then
- if err then fail(err)
+ if err then fail(err)
else pass("ok") end
- else
- if alldone then
- if err then fail("unexpected error '%s'", err)
+ else
+ if alldone then
+ if err then fail("unexpected error '%s'", err)
else pass("ok") end
else
- if err ~= "timeout" then fail(err)
+ if err ~= "timeout" then fail(err)
else pass("proper timeoutk") end
end
end
- else
- if err then fail(err)
- else pass("ok") end
+ else
+ if err then fail(err)
+ else pass("ok") end
end
end
end
@@ -104,8 +104,8 @@ control:setoption("tcp-nodelay", true)
------------------------------------------------------------------------
function test_methods(sock, methods)
for _, v in pairs(methods) do
- if type(sock[v]) ~= "function" then
- fail(sock.class .. " method '" .. v .. "' not registered")
+ if type(sock[v]) ~= "function" then
+ fail(sock.class .. " method '" .. v .. "' not registered")
end
end
pass(sock.class .. " methods are ok")
@@ -121,7 +121,7 @@ function test_mixed(len)
local p3 = "raw " .. string.rep("z", inter) .. "bytes"
local p4 = "end" .. string.rep("w", inter) .. "bytes"
local bp1, bp2, bp3, bp4
-remote (string.format("str = data:receive(%d)",
+remote (string.format("str = data:receive(%d)",
string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
sent, err = data:send(p1..p2..p3..p4)
if err then fail(err) end
@@ -166,7 +166,7 @@ function test_rawline(len)
io.stderr:write("length " .. len .. ": ")
local str, str10, back, err
str = string.rep(string.char(47), math.mod(len, 10))
- str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
+ str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
math.floor(len/10))
str = str .. str10
remote "str = data:receive()"
@@ -216,7 +216,7 @@ function test_totaltimeoutreceive(len, tm, sl)
data:settimeout(tm, "total")
local t = socket.gettime()
str, err, partial, elapsed = data:receive(2*len)
- check_timeout(tm, sl, elapsed, err, "receive", "total",
+ check_timeout(tm, sl, elapsed, err, "receive", "total",
string.len(str or partial) == 2*len)
end
@@ -236,7 +236,7 @@ function test_totaltimeoutsend(len, tm, sl)
data:settimeout(tm, "total")
str = string.rep("a", 2*len)
total, err, partial, elapsed = data:send(str)
- check_timeout(tm, sl, elapsed, err, "send", "total",
+ check_timeout(tm, sl, elapsed, err, "send", "total",
total == 2*len)
end
@@ -256,7 +256,7 @@ function test_blockingtimeoutreceive(len, tm, sl)
]], 2*tm, len, sl, sl))
data:settimeout(tm)
str, err, partial, elapsed = data:receive(2*len)
- check_timeout(tm, sl, elapsed, err, "receive", "blocking",
+ check_timeout(tm, sl, elapsed, err, "receive", "blocking",
string.len(str or partial) == 2*len)
end
@@ -290,10 +290,10 @@ function empty_connect()
data = server:accept()
]]
data, err = socket.connect("", port)
- if not data then
+ if not data then
pass("ok")
data = socket.connect(host, port)
- else
+ else
pass("gethostbyname returns localhost on empty string...")
end
end
@@ -327,7 +327,7 @@ function test_closed()
data:close()
data = nil
]], str))
- -- try to get a line
+ -- try to get a line
back, err, partial = data:receive()
if not err then fail("should have gotten 'closed'.")
elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.")
@@ -340,25 +340,25 @@ function test_closed()
data = nil
]]
total, err, partial = data:send(string.rep("ugauga", 100000))
- if not err then
+ if not err then
pass("failed: output buffer is at least %d bytes long!", total)
- elseif err ~= "closed" then
+ elseif err ~= "closed" then
fail("got '"..err.."' instead of 'closed'.")
- else
- pass("graceful 'closed' received after %d bytes were sent", partial)
+ else
+ pass("graceful 'closed' received after %d bytes were sent", partial)
end
end
------------------------------------------------------------------------
function test_selectbugs()
local r, s, e = socket.select(nil, nil, 0.1)
- assert(type(r) == "table" and type(s) == "table" and
+ assert(type(r) == "table" and type(s) == "table" and
(e == "timeout" or e == "error"))
pass("both nil: ok")
local udp = socket.udp()
udp:close()
r, s, e = socket.select({ udp }, { udp }, 0.1)
- assert(type(r) == "table" and type(s) == "table" and
+ assert(type(r) == "table" and type(s) == "table" and
(e == "timeout" or e == "error"))
pass("closed sockets: ok")
e = pcall(socket.select, "wrong", 1, 0.1)
@@ -389,7 +389,7 @@ function accept_timeout()
local t = socket.gettime()
s:settimeout(1)
local c, e = s:accept()
- assert(not c, "should not accept")
+ assert(not c, "should not accept")
assert(e == "timeout", string.format("wrong error message (%s)", e))
t = socket.gettime() - t
assert(t < 2, string.format("took to long to give up (%gs)", t))
@@ -407,9 +407,9 @@ function connect_timeout()
local t = socket.gettime()
local r, e = c:connect("10.0.0.1", 81)
assert(not r, "should not connect")
- assert(socket.gettime() - t < 2, "took too long to give up.")
+ assert(socket.gettime() - t < 2, "took too long to give up.")
c:close()
- pass("ok")
+ pass("ok")
end
------------------------------------------------------------------------
@@ -447,16 +447,14 @@ end
------------------------------------------------------------------------
function rebind_test()
- --local c ,c1 = socket.bind("localhost", 0)
local c ,c1 = socket.bind("127.0.0.1", 0)
if not c then pass ("failed to bind! " .. tostring(c) .. ' ' .. tostring(c1)) return end
assert(c,c1)
-
local i, p = c:getsockname()
local s, e = socket.tcp()
assert(s, e)
s:setoption("reuseaddr", false)
- r, e = s:bind("localhost", p)
+ r, e = s:bind(i, p)
assert(not r, "managed to rebind!")
assert(e)
pass("ok")
@@ -476,9 +474,9 @@ function getstats_test()
data:receive(c)
t = t + c
local r, s, a = data:getstats()
- assert(r == t, "received count failed" .. tostring(r)
+ assert(r == t, "received count failed" .. tostring(r)
.. "/" .. tostring(t))
- assert(s == t, "sent count failed" .. tostring(s)
+ assert(s == t, "sent count failed" .. tostring(s)
.. "/" .. tostring(t))
end
pass("ok")
@@ -486,7 +484,7 @@ end
------------------------------------------------------------------------
-function test_nonblocking(size)
+function test_nonblocking(size)
reconnect()
printf("testing " .. 2*size .. " bytes: ")
remote(string.format([[
@@ -545,7 +543,7 @@ function test_readafterclose()
data:close()
data = nil
]]))
- data:close()
+ data:close()
back, err, partial = data:receive("*a")
assert(back == nil and err == "closed", "should have returned 'closed'")
pass("ok")
@@ -555,7 +553,7 @@ function test_readafterclose()
data:close()
data = nil
]]))
- data:close()
+ data:close()
back, err, partial = data:receive()
assert(back == nil and err == "closed", "should have returned 'closed'")
pass("ok")
@@ -565,7 +563,7 @@ function test_readafterclose()
data:close()
data = nil
]]))
- data:close()
+ data:close()
back, err, partial = data:receive(1)
assert(back == nil and err == "closed", "should have returned 'closed'")
pass("ok")
@@ -575,7 +573,7 @@ function test_readafterclose()
data:close()
data = nil
]]))
- data:close()
+ data:close()
back, err, partial = data:receive(0)
assert(back == nil and err == "closed", "should have returned 'closed'")
pass("ok")
@@ -593,7 +591,7 @@ function test_writeafterclose()
while not err do
sent, err, errsent, time = data:send(str)
end
- assert(err == "closed", "should have returned 'closed'")
+ assert(err == "closed", "got " .. err .. " instead of 'closed'")
pass("ok")
end
@@ -648,18 +646,18 @@ else io.stderr:write("Warning! IPv6 does not support!\n") end
end
local udp_methods = {
- "close",
+ "close",
"dirty",
"getfamily",
"getfd",
"getoption",
"getpeername",
"getsockname",
- "receive",
- "receivefrom",
- "send",
- "sendto",
- "setfd",
+ "receive",
+ "receivefrom",
+ "send",
+ "sendto",
+ "setfd",
"setoption",
"setpeername",
"setsockname",
@@ -674,6 +672,9 @@ if sock then test_methods(socket.udp6(), udp_methods)
else io.stderr:write("Warning! IPv6 does not support!\n") end
end
+test("closed connection detection: ")
+test_closed()
+
test("partial receive")
test_partialrecv()
@@ -697,9 +698,6 @@ rebind_test()
test("active close: ")
active_close()
-test("closed connection detection: ")
-test_closed()
-
test("accept function: ")
accept_timeout()
accept_errors()
diff --git a/test/testsrvr.lua b/test/testsrvr.lua
index 72b93ab..1eb2d5b 100644
--- a/test/testsrvr.lua
+++ b/test/testsrvr.lua
@@ -6,7 +6,7 @@ ack = "\n";
while 1 do
print("server: waiting for client connection...");
control = assert(server:accept());
- while 1 do
+ while 1 do
command, emsg = control:receive();
if emsg == "closed" then
control:close()
diff --git a/test/udpconnectclnt.lua b/test/udpconnectclnt.lua
index effe13a..ad6ab6a 100644
--- a/test/udpconnectclnt.lua
+++ b/test/udpconnectclnt.lua
@@ -1,7 +1,7 @@
local socket = require"socket"
local udp = socket.udp
local localhost = "127.0.0.1"
-local port = arg[1]
+local port = assert(arg[1], "missing port argument")
se = udp(); se:setoption("reuseaddr", true)
se:setsockname(localhost, 5062)
--
cgit v1.2.3-55-g6feb
From 77bba625d7aaa0f9e118879163687fcbcb0b5a7b Mon Sep 17 00:00:00 2001
From: Diego Nehab
Date: Tue, 25 Aug 2015 15:41:40 -0300
Subject: Fixes suggested by @Florob in #147.
---
doc/tcp.html | 6 ++++++
doc/udp.html | 6 ++++++
src/inet.c | 17 +++++++++++------
src/inet.h | 2 +-
src/tcp.c | 52 +++++++++++++++++++++-------------------------------
src/udp.c | 52 +++++++++++++++++++++-------------------------------
test/testclnt.lua | 19 ++++++++++++-------
7 files changed, 78 insertions(+), 76 deletions(-)
(limited to 'test')
diff --git a/doc/tcp.html b/doc/tcp.html
index 6fc9900..fb627a1 100644
--- a/doc/tcp.html
+++ b/doc/tcp.html
@@ -65,6 +65,12 @@ href=#bind>connect, depending on the address
family obtained from the resolver.
+
+Note: Before the choice between IPv4 and IPv6 happens,
+the internal socket object is invalid and therefore setoption will fail.
+
+
diff --git a/doc/udp.html b/doc/udp.html
index e313af4..a300f2f 100644
--- a/doc/udp.html
+++ b/doc/udp.html
@@ -76,6 +76,12 @@ href=#setsockname>sockname, depending on the address
family obtained from the resolver.
+
+Note: Before the choice between IPv4 and IPv6 happens,
+the internal socket object is invalid and therefore setoption will fail.
+
+
diff --git a/src/inet.c b/src/inet.c
index 8f0fac2..331b800 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -352,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
/*-------------------------------------------------------------------------*\
* Tries to create a new inet socket
\*-------------------------------------------------------------------------*/
-const char *inet_trycreate(p_socket ps, int family, int type) {
- return socket_strerror(socket_create(ps, family, type, 0));
+const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
+ const char *err = socket_strerror(socket_create(ps, family, type, protocol));
+ if (err == NULL && family == AF_INET6) {
+ int yes = 1;
+ setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
+ }
+ return err;
}
/*-------------------------------------------------------------------------*\
@@ -408,8 +413,8 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
* not enter this branch. */
if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
socket_destroy(ps);
- err = socket_strerror(socket_create(ps, iterator->ai_family,
- iterator->ai_socktype, iterator->ai_protocol));
+ err = inet_trycreate(ps, iterator->ai_family,
+ iterator->ai_socktype, iterator->ai_protocol);
if (err) continue;
current_family = iterator->ai_family;
/* set non-blocking before connect */
@@ -466,8 +471,8 @@ const char *inet_trybind(p_socket ps, int *family, const char *address,
for (iterator = resolved; iterator; iterator = iterator->ai_next) {
if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
socket_destroy(ps);
- err = socket_strerror(socket_create(ps, iterator->ai_family,
- iterator->ai_socktype, iterator->ai_protocol));
+ err = inet_trycreate(ps, iterator->ai_family,
+ iterator->ai_socktype, iterator->ai_protocol);
if (err) continue;
current_family = iterator->ai_family;
}
diff --git a/src/inet.h b/src/inet.h
index b85c20e..feb3541 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -24,7 +24,7 @@
int inet_open(lua_State *L);
-const char *inet_trycreate(p_socket ps, int family, int type);
+const char *inet_trycreate(p_socket ps, int family, int type, int protocol);
const char *inet_tryconnect(p_socket ps, int *family, const char *address,
const char *serv, p_timeout tm, struct addrinfo *connecthints);
const char *inet_trybind(p_socket ps, int *family, const char *address,
diff --git a/src/tcp.c b/src/tcp.c
index 4d12f08..7bf1af5 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -355,39 +355,29 @@ static int meth_settimeout(lua_State *L)
* Creates a master tcp object
\*-------------------------------------------------------------------------*/
static int tcp_create(lua_State *L, int family) {
- t_socket sock;
- /* if family is AF_UNSPEC, we create an AF_INET socket
- * but store AF_UNSPEC into tcp-family. This will allow it
- * later be replaced with an AF_INET6 socket if
- * trybind or tryconnect prefer it instead. */
- const char *err = inet_trycreate(&sock, family == AF_UNSPEC?
- AF_INET: family, SOCK_STREAM);
- /* try to allocate a system socket */
- if (!err) {
- /* allocate tcp object */
- p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
- memset(tcp, 0, sizeof(t_tcp));
- /* set its type as master object */
- auxiliar_setclass(L, "tcp{master}", -1);
- /* initialize remaining structure fields */
- socket_setnonblocking(&sock);
- if (family == AF_INET6) {
- int yes = 1;
- setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
- (void *)&yes, sizeof(yes));
+ p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
+ memset(tcp, 0, sizeof(t_tcp));
+ /* set its type as master object */
+ auxiliar_setclass(L, "tcp{master}", -1);
+ /* if family is AF_UNSPEC, we leave the socket invalid and
+ * store AF_UNSPEC into family. This will allow it to later be
+ * replaced with an AF_INET6 or AF_INET socket upon first use. */
+ tcp->sock = SOCKET_INVALID;
+ tcp->family = family;
+ io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
+ (p_error) socket_ioerror, &tcp->sock);
+ timeout_init(&tcp->tm, -1, -1);
+ buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
+ if (family != AF_UNSPEC) {
+ const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0);
+ if (err != NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
}
- tcp->sock = sock;
- io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
- (p_error) socket_ioerror, &tcp->sock);
- timeout_init(&tcp->tm, -1, -1);
- buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
- tcp->family = family;
- return 1;
- } else {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
+ socket_setnonblocking(&tcp->sock);
}
+ return 1;
}
static int global_create(lua_State *L) {
diff --git a/src/udp.c b/src/udp.c
index 6600859..17d932a 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -185,7 +185,7 @@ static int meth_sendto(lua_State *L) {
return 2;
}
timeout_markstart(tm);
- err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
+ err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
(socklen_t) ai->ai_addrlen, tm);
freeaddrinfo(ai);
if (err != IO_DONE) {
@@ -237,7 +237,7 @@ static int meth_receivefrom(lua_State *L)
char portstr[6];
timeout_markstart(tm);
count = MIN(count, sizeof(buffer));
- err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr,
+ err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr,
&addr_len, tm);
/* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
if (err == IO_CLOSED)
@@ -247,7 +247,7 @@ static int meth_receivefrom(lua_State *L)
lua_pushstring(L, udp_strerror(err));
return 2;
}
- err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
+ err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
if (err) {
lua_pushnil(L);
@@ -351,7 +351,7 @@ static int meth_setpeername(lua_State *L) {
/* make sure we try to connect only to the same family */
connecthints.ai_family = udp->family;
if (connecting) {
- err = inet_tryconnect(&udp->sock, &udp->family, address,
+ err = inet_tryconnect(&udp->sock, &udp->family, address,
port, tm, &connecthints);
if (err) {
lua_pushnil(L);
@@ -365,7 +365,6 @@ static int meth_setpeername(lua_State *L) {
inet_trydisconnect(&udp->sock, udp->family, tm);
auxiliar_setclass(L, "udp{unconnected}", 1);
}
- /* change class to connected or unconnected depending on address */
lua_pushnumber(L, 1);
return 1;
}
@@ -410,34 +409,25 @@ static int meth_setsockname(lua_State *L) {
* Creates a master udp object
\*-------------------------------------------------------------------------*/
static int udp_create(lua_State *L, int family) {
- t_socket sock;
- /* if family is AF_UNSPEC, we create an AF_INET socket
- * but store AF_UNSPEC into tcp-family. This will allow it
- * later be replaced with an AF_INET6 socket if
- * trybind or tryconnect prefer it instead. */
- const char *err = inet_trycreate(&sock, family == AF_UNSPEC?
- AF_INET: family, SOCK_DGRAM);
- /* try to allocate a system socket */
- if (!err) {
- /* allocate udp object */
- p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
- auxiliar_setclass(L, "udp{unconnected}", -1);
- /* initialize remaining structure fields */
- socket_setnonblocking(&sock);
- if (family == AF_INET6) {
- int yes = 1;
- setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
- (void *)&yes, sizeof(yes));
+ /* allocate udp object */
+ p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
+ auxiliar_setclass(L, "udp{unconnected}", -1);
+ /* if family is AF_UNSPEC, we leave the socket invalid and
+ * store AF_UNSPEC into family. This will allow it to later be
+ * replaced with an AF_INET6 or AF_INET socket upon first use. */
+ udp->sock = SOCKET_INVALID;
+ timeout_init(&udp->tm, -1, -1);
+ udp->family = family;
+ if (family != AF_UNSPEC) {
+ const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
+ if (err != NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
}
- udp->sock = sock;
- timeout_init(&udp->tm, -1, -1);
- udp->family = family;
- return 1;
- } else {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
+ socket_setnonblocking(&udp->sock);
}
+ return 1;
}
static int global_create(lua_State *L) {
diff --git a/test/testclnt.lua b/test/testclnt.lua
index abf9608..ee1201f 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -304,15 +304,20 @@ function isclosed(c)
end
function active_close()
- reconnect()
- if isclosed(data) then fail("should not be closed") end
- data:close()
- if not isclosed(data) then fail("should be closed") end
- data = nil
- local udp = socket.udp()
+ local tcp = socket.tcp4()
+ if isclosed(tcp) then fail("should not be closed") end
+ tcp:close()
+ if not isclosed(tcp) then fail("should be closed") end
+ tcp = socket.tcp()
+ if not isclosed(tcp) then fail("should be closed") end
+ tcp = nil
+ local udp = socket.udp4()
if isclosed(udp) then fail("should not be closed") end
udp:close()
if not isclosed(udp) then fail("should be closed") end
+ udp = socket.udp()
+ if not isclosed(udp) then fail("should be closed") end
+ udp = nil
pass("ok")
end
@@ -368,7 +373,7 @@ function test_selectbugs()
pass("invalid input: ok")
local toomany = {}
for i = 1, socket._SETSIZE+1 do
- toomany[#toomany+1] = socket.udp()
+ toomany[#toomany+1] = socket.udp4()
end
if #toomany > socket._SETSIZE then
local e = pcall(socket.select, toomany, nil, 0.1)
--
cgit v1.2.3-55-g6feb