From 2906d6a5227df25f14305c373fdde057f388d363 Mon Sep 17 00:00:00 2001
From: Victor Seva
Date: Fri, 5 Dec 2014 13:17:50 +0100
Subject: Add "tcp-keepidle", "tcp-keepcnt" and "tcp-keepintvl" options
---
test/tcp-getoptions | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
(limited to 'test')
diff --git a/test/tcp-getoptions b/test/tcp-getoptions
index f9b3d1b..777ccc3 100755
--- a/test/tcp-getoptions
+++ b/test/tcp-getoptions
@@ -7,7 +7,9 @@ port = 8765
function options(o)
print("options for", o)
- for _, opt in ipairs{"keepalive", "reuseaddr", "tcp-nodelay"} do
+ for _, opt in ipairs{
+ "keepalive", "reuseaddr",
+ "tcp-nodelay", "tcp-keepidle", "tcp-keepcnt", "tcp-keepintvl"} do
print("getoption", opt, o:getoption(opt))
end
--
cgit v1.2.3-55-g6feb
From be67f63f4e11e53690bf1431a236f86b484c9bf0 Mon Sep 17 00:00:00 2001
From: Diego Nehab
Date: Tue, 6 Oct 2015 11:33:50 +0800
Subject: Changed buffer-per-socket to buffer-per-operation.
This is a difficult tradeoff to measure. I think large
datagrams won't be used very frequently. So it is better to
not lock a large buffer to each socket object and instead
allocate and deallocate for each operation receiving a
datagram larger than UDP_DATAGRAMSIZE.
---
doc/reference.html | 2 ++
doc/socket.html | 25 ++++++++++++++++++++++-
doc/udp.html | 33 +++++++------------------------
src/select.c | 5 ++++-
src/udp.c | 58 +++++++++++++++++++++++++-----------------------------
src/udp.h | 2 --
test/testclnt.lua | 1 -
7 files changed, 64 insertions(+), 62 deletions(-)
(limited to 'test')
diff --git a/doc/reference.html b/doc/reference.html
index 6067ba6..878e7d2 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -147,6 +147,7 @@ Support, Manual">
connect,
connect4,
connect6,
+_DATAGRAMSIZE,
_DEBUG,
dns,
gettime,
@@ -158,6 +159,7 @@ Support, Manual">
skip,
sleep,
_SETSIZE,
+_SOCKETINVALID,
source,
tcp,
tcp4,
diff --git a/doc/socket.html b/doc/socket.html
index e6a9bf8..8a81414 100644
--- a/doc/socket.html
+++ b/doc/socket.html
@@ -90,7 +90,7 @@ of connect are defined as simple helper functions that restrict the
-
+
socket._DEBUG
@@ -99,6 +99,19 @@ This constant is set to true if the library was compiled
with debug support.
+
+
+
+socket._DATAGRAMSIZE
+
+
+
+Default datagram size used by calls to
+receive and
+receivefrom.
+(Unless changed in compile time, the value is 8192.)
+
+
@@ -393,6 +406,16 @@ The maximum number of sockets that the select function can handle.
+
+
+
+socket._SOCKETINVALID
+
+
+
+The OS value for an invalid socket.
+
+
diff --git a/doc/udp.html b/doc/udp.html
index 22d7c72..9437c51 100644
--- a/doc/udp.html
+++ b/doc/udp.html
@@ -42,7 +42,7 @@
-socket.udp([buffersize])
+socket.udp()
@@ -62,13 +62,6 @@ The setpeername
is used to connect the object.
-
-The optional buffersize parameter
-specifies the size of the largest datagram that will
-ever be received by the UDP object. The default value is
-8192.
-
-
In case of success, a new unconnected UDP object
returned. In case of error, nil is returned, followed by
@@ -92,7 +85,7 @@ href=#setoption>setoption will fail.
-socket.udp4([buffersize])
+socket.udp4()
@@ -112,13 +105,6 @@ The setpeername
is used to connect the object.
-
-The optional buffersize parameter
-specifies the size of the largest datagram that will
-ever be received by the UDP object. The default value is
-8192.
-
-
In case of success, a new unconnected UDP object
returned. In case of error, nil is returned, followed by
@@ -128,7 +114,7 @@ an error message.
-socket.udp6([buffersize])
+socket.udp6()
@@ -148,13 +134,6 @@ The setpeername
is used to connect the object.
-
-The optional buffersize parameter
-specifies the size of the largest datagram that will
-ever be received by the UDP object. The default value is
-8192.
-
-
In case of success, a new unconnected UDP object
returned. In case of error, nil is returned, followed by
@@ -261,8 +240,10 @@ the excess bytes are discarded. If there are less then
size bytes available in the current datagram, the
available bytes are returned.
If size is omitted, the
-buffersize argument at creation time is used
-(which defaults to 8192 bytes).
+compile-time constant socket._DATAGRAMSIZE is used
+(it defaults to 8192 bytes). Larger sizes will cause a
+temporary buffer to be allocated for the operation.
diff --git a/src/select.c b/src/select.c
index d14c40a..9d133b7 100644
--- a/src/select.c
+++ b/src/select.c
@@ -39,7 +39,10 @@ static luaL_Reg func[] = {
\*-------------------------------------------------------------------------*/
int select_open(lua_State *L) {
lua_pushstring(L, "_SETSIZE");
- lua_pushnumber(L, FD_SETSIZE);
+ lua_pushinteger(L, FD_SETSIZE);
+ lua_rawset(L, -3);
+ lua_pushstring(L, "_SOCKETINVALID");
+ lua_pushinteger(L, SOCKET_INVALID);
lua_rawset(L, -3);
luaL_setfuncs(L, func, 0);
return 0;
diff --git a/src/udp.c b/src/udp.c
index 9c27b60..968dca8 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -41,7 +41,6 @@ static int meth_setpeername(lua_State *L);
static int meth_close(lua_State *L);
static int meth_setoption(lua_State *L);
static int meth_getoption(lua_State *L);
-static int meth_getbufferlength(lua_State *L);
static int meth_settimeout(lua_State *L);
static int meth_getfd(lua_State *L);
static int meth_setfd(lua_State *L);
@@ -64,7 +63,6 @@ static luaL_Reg udp_methods[] = {
{"setfd", meth_setfd},
{"setoption", meth_setoption},
{"getoption", meth_getoption},
- {"getoption", meth_getbufferlength},
{"setpeername", meth_setpeername},
{"setsockname", meth_setsockname},
{"settimeout", meth_settimeout},
@@ -118,8 +116,7 @@ static luaL_Reg func[] = {
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
-int udp_open(lua_State *L)
-{
+int udp_open(lua_State *L) {
/* create classes */
auxiliar_newclass(L, "udp{connected}", udp_methods);
auxiliar_newclass(L, "udp{unconnected}", udp_methods);
@@ -130,6 +127,10 @@ int udp_open(lua_State *L)
auxiliar_add2group(L, "udp{unconnected}", "select{able}");
/* define library functions */
luaL_setfuncs(L, func, 0);
+ /* export default UDP size */
+ lua_pushliteral(L, "_DATAGRAMSIZE");
+ lua_pushinteger(L, UDP_DATAGRAMSIZE);
+ lua_rawset(L, -3);
return 0;
}
@@ -205,30 +206,26 @@ static int meth_sendto(lua_State *L) {
static int meth_receive(lua_State *L) {
p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
char buf[UDP_DATAGRAMSIZE];
- size_t len = MAX(udp->len, UDP_DATAGRAMSIZE);
- char *dgram = len > sizeof(buf)? udp->buf: buf;
- size_t got, wanted = (size_t) luaL_optnumber(L, 2, len);
+ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
int err;
p_timeout tm = &udp->tm;
timeout_markstart(tm);
- wanted = MIN(wanted, len);
+ if (!dgram) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "out of memory");
+ return 2;
+ }
err = socket_recv(&udp->sock, dgram, wanted, &got, tm);
/* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
- if (err != IO_DONE && err != IO_CLOSED ) {
+ if (err != IO_DONE && err != IO_CLOSED) {
lua_pushnil(L);
lua_pushstring(L, udp_strerror(err));
+ if (wanted > sizeof(buf)) free(dgram);
return 2;
}
lua_pushlstring(L, dgram, got);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Receives data from a UDP socket
-\*-------------------------------------------------------------------------*/
-static int meth_getbufferlength(lua_State *L) {
- p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
- lua_pushinteger(L, MAX(UDP_DATAGRAMSIZE, udp->len));
+ if (wanted > sizeof(buf)) free(dgram);
return 1;
}
@@ -238,9 +235,8 @@ static int meth_getbufferlength(lua_State *L) {
static int meth_receivefrom(lua_State *L) {
p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
char buf[UDP_DATAGRAMSIZE];
- size_t len = MAX(udp->len, UDP_DATAGRAMSIZE);
- char *dgram = len > sizeof(buf)? udp->buf: buf;
- size_t got, wanted = (size_t) luaL_optnumber(L, 2, len);
+ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
char addrstr[INET6_ADDRSTRLEN];
@@ -248,13 +244,18 @@ static int meth_receivefrom(lua_State *L) {
int err;
p_timeout tm = &udp->tm;
timeout_markstart(tm);
- wanted = MIN(wanted, len);
+ if (!dgram) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "out of memory");
+ return 2;
+ }
err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr,
&addr_len, tm);
/* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
if (err != IO_DONE && err != IO_CLOSED) {
lua_pushnil(L);
lua_pushstring(L, udp_strerror(err));
+ if (wanted > sizeof(buf)) free(dgram);
return 2;
}
err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
@@ -262,19 +263,20 @@ static int meth_receivefrom(lua_State *L) {
if (err) {
lua_pushnil(L);
lua_pushstring(L, gai_strerror(err));
+ if (wanted > sizeof(buf)) free(dgram);
return 2;
}
lua_pushlstring(L, dgram, got);
lua_pushstring(L, addrstr);
lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10));
+ if (wanted > sizeof(buf)) free(dgram);
return 3;
}
/*-------------------------------------------------------------------------*\
* Returns family as string
\*-------------------------------------------------------------------------*/
-static int meth_getfamily(lua_State *L)
-{
+static int meth_getfamily(lua_State *L) {
p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
if (udp->family == AF_INET6) {
lua_pushliteral(L, "inet6");
@@ -419,19 +421,13 @@ static int meth_setsockname(lua_State *L) {
* Creates a master udp object
\*-------------------------------------------------------------------------*/
static int udp_create(lua_State *L, int family) {
- p_udp udp = NULL;
- /* optional length for private datagram buffer. this is useful when
- * you need larger datagrams than UDP_DATAGRAMSIZE */
- size_t len = (size_t) luaL_optinteger(L, 1, 0);
- if (len <= UDP_DATAGRAMSIZE) len = 0;
/* allocate udp object */
- udp = (p_udp) lua_newuserdata(L, sizeof(t_udp) + len - 1);
+ 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;
- udp->len = len;
timeout_init(&udp->tm, -1, -1);
udp->family = family;
if (family != AF_UNSPEC) {
diff --git a/src/udp.h b/src/udp.h
index da27a7a..be9b6a5 100644
--- a/src/udp.h
+++ b/src/udp.h
@@ -23,8 +23,6 @@ typedef struct t_udp_ {
t_socket sock;
t_timeout tm;
int family;
- size_t len; /* length of datagram buffer below */
- char buf[1]; /* allocate larger structure to hold actual buffer */
} t_udp;
typedef t_udp *p_udp;
diff --git a/test/testclnt.lua b/test/testclnt.lua
index ee1201f..170e187 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -669,7 +669,6 @@ local udp_methods = {
"settimeout"
}
-
------------------------------------------------------------------------
test_methods(socket.udp(), udp_methods)
do local sock = socket.tcp6()
--
cgit v1.2.3-55-g6feb
From fb713cdedb16f8eb67523f17b0d66262b4e9dca1 Mon Sep 17 00:00:00 2001
From: mpeterv
Date: Mon, 25 Jan 2016 15:14:34 +0300
Subject: Add more tests for socket.try/protect
---
test/excepttest.lua | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
(limited to 'test')
diff --git a/test/excepttest.lua b/test/excepttest.lua
index ce9f197..6904545 100644
--- a/test/excepttest.lua
+++ b/test/excepttest.lua
@@ -1,6 +1,31 @@
local socket = require("socket")
-try = socket.newtry(function()
- print("finalized!!!")
+
+local finalizer_called
+
+local func = socket.protect(function(err, ...)
+ local try = socket.newtry(function()
+ finalizer_called = true
+ error("ignored")
+ end)
+
+ if err then
+ return error(err, 0)
+ else
+ return try(...)
+ end
end)
-try = socket.protect(try)
-print(try(nil, "it works"))
+
+local ret1, ret2, ret3 = func(false, 1, 2, 3)
+assert(not finalizer_called, "unexpected finalizer call")
+assert(ret1 == 1 and ret2 == 2 and ret3 == 3, "incorrect return values")
+
+ret1, ret2, ret3 = func(false, false, "error message")
+assert(finalizer_called, "finalizer not called")
+assert(ret1 == nil and ret2 == "error message" and ret3 == nil, "incorrect return values")
+
+local err = {key = "value"}
+ret1, ret2 = pcall(func, err)
+assert(not ret1, "error not rethrown")
+assert(ret2 == err, "incorrect error rethrown")
+
+print("OK")
--
cgit v1.2.3-55-g6feb
From 9fe38c654f6c62a4f11d993bd79c710af9313fbd Mon Sep 17 00:00:00 2001
From: Philipp Janda
Date: Wed, 24 Feb 2016 00:48:43 +0100
Subject: Don't swallow errors in finalizers.
---
doc/socket.html | 3 +--
src/except.c | 2 +-
test/excepttest.lua | 1 -
3 files changed, 2 insertions(+), 4 deletions(-)
(limited to 'test')
diff --git a/doc/socket.html b/doc/socket.html
index a43a208..08ef784 100644
--- a/doc/socket.html
+++ b/doc/socket.html
@@ -167,8 +167,7 @@ is raised.
Finalizer is a function that will be called before
-try throws the exception. It will be called
-in protected mode.
+try throws the exception.
diff --git a/src/except.c b/src/except.c
index def35a0..309f8f0 100644
--- a/src/except.c
+++ b/src/except.c
@@ -49,7 +49,7 @@ static void wrap(lua_State *L) {
static int finalize(lua_State *L) {
if (!lua_toboolean(L, 1)) {
lua_pushvalue(L, lua_upvalueindex(1));
- lua_pcall(L, 0, 0, 0);
+ lua_call(L, 0, 0);
lua_settop(L, 2);
wrap(L);
lua_error(L);
diff --git a/test/excepttest.lua b/test/excepttest.lua
index 6904545..80c9cb8 100644
--- a/test/excepttest.lua
+++ b/test/excepttest.lua
@@ -5,7 +5,6 @@ local finalizer_called
local func = socket.protect(function(err, ...)
local try = socket.newtry(function()
finalizer_called = true
- error("ignored")
end)
if err then
--
cgit v1.2.3-55-g6feb
From 916b548240b1513410b13f964d80f329aec9c13a Mon Sep 17 00:00:00 2001
From: Diego Nehab
Date: Mon, 7 Mar 2016 01:30:30 -0300
Subject: Family agostic FTP and expose HTTP/FTP url parsing
---
src/ftp.lua | 67 ++++++++++++++++++++++++++++++++++++++++++--------------
src/http.lua | 17 ++++++++++----
src/tp.lua | 10 ++++++++-
test/ftptest.lua | 34 ++++++++++++++++++----------
4 files changed, 96 insertions(+), 32 deletions(-)
(limited to 'test')
diff --git a/src/ftp.lua b/src/ftp.lua
index e0c3cae..11798ad 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -51,7 +51,7 @@ end
function metat.__index:pasvconnect()
self.data = self.try(socket.tcp())
self.try(self.data:settimeout(_M.TIMEOUT))
- self.try(self.data:connect(self.pasvt.ip, self.pasvt.port))
+ self.try(self.data:connect(self.pasvt.address, self.pasvt.port))
end
function metat.__index:login(user, password)
@@ -71,32 +71,65 @@ function metat.__index:pasv()
local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
self.try(a and b and c and d and p1 and p2, reply)
self.pasvt = {
- ip = string.format("%d.%d.%d.%d", a, b, c, d),
+ address = string.format("%d.%d.%d.%d", a, b, c, d),
port = p1*256 + p2
}
if self.server then
self.server:close()
self.server = nil
end
- return self.pasvt.ip, self.pasvt.port
+ return self.pasvt.address, self.pasvt.port
end
-function metat.__index:port(ip, port)
+function metat.__index:epsv()
+ self.try(self.tp:command("epsv"))
+ local code, reply = self.try(self.tp:check("229"))
+ local pattern = "%((.)(.-)%1(.-)%1(.-)%1%)"
+ local d, prt, address, port = string.match(reply, pattern)
+ self.try(port, "invalid epsv response")
+ self.pasvt = {
+ address = self.tp:getpeername(),
+ port = port
+ }
+ if self.server then
+ self.server:close()
+ self.server = nil
+ end
+ return self.pasvt.address, self.pasvt.port
+end
+
+
+function metat.__index:port(address, port)
self.pasvt = nil
- if not ip then
- ip, port = self.try(self.tp:getcontrol():getsockname())
- self.server = self.try(socket.bind(ip, 0))
- ip, port = self.try(self.server:getsockname())
+ if not address then
+ address, port = self.try(self.tp:getsockname())
+ self.server = self.try(socket.bind(address, 0))
+ address, port = self.try(self.server:getsockname())
self.try(self.server:settimeout(_M.TIMEOUT))
end
local pl = math.mod(port, 256)
local ph = (port - pl)/256
- local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",")
+ local arg = string.gsub(string.format("%s,%d,%d", address, ph, pl), "%.", ",")
self.try(self.tp:command("port", arg))
self.try(self.tp:check("2.."))
return 1
end
+function metat.__index:eprt(family, address, port)
+ self.pasvt = nil
+ if not address then
+ address, port = self.try(self.tp:getsockname())
+ self.server = self.try(socket.bind(address, 0))
+ address, port = self.try(self.server:getsockname())
+ self.try(self.server:settimeout(_M.TIMEOUT))
+ end
+ local arg = string.format("|%s|%s|%d|", family, address, port)
+ self.try(self.tp:command("eprt", arg))
+ self.try(self.tp:check("2.."))
+ return 1
+end
+
+
function metat.__index:send(sendt)
self.try(self.pasvt or self.server, "need port or pasv first")
-- if there is a pasvt table, we already sent a PASV command
@@ -110,12 +143,12 @@ function metat.__index:send(sendt)
-- send the transfer command and check the reply
self.try(self.tp:command(command, argument))
local code, reply = self.try(self.tp:check{"2..", "1.."})
- -- if there is not a a pasvt table, then there is a server
+ -- if there is not a pasvt table, then there is a server
-- and we already sent a PORT command
if not self.pasvt then self:portconnect() end
-- get the sink, source and step for the transfer
local step = sendt.step or ltn12.pump.step
- local readt = {self.tp.c}
+ local readt = { self.tp }
local checkstep = function(src, snk)
-- check status in control connection while downloading
local readyt = socket.select(readt, nil, 0)
@@ -207,7 +240,7 @@ local function tput(putt)
f:greet()
f:login(putt.user, putt.password)
if putt.type then f:type(putt.type) end
- f:pasv()
+ f:epsv()
local sent = f:send(putt)
f:quit()
f:close()
@@ -219,7 +252,7 @@ local default = {
scheme = "ftp"
}
-local function parse(u)
+local function genericform(u)
local t = socket.try(url.parse(u, default))
socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
socket.try(t.host, "missing hostname")
@@ -232,8 +265,10 @@ local function parse(u)
return t
end
+_M.genericform = genericform
+
local function sput(u, body)
- local putt = parse(u)
+ local putt = genericform(u)
putt.source = ltn12.source.string(body)
return tput(putt)
end
@@ -250,14 +285,14 @@ local function tget(gett)
f:greet()
f:login(gett.user, gett.password)
if gett.type then f:type(gett.type) end
- f:pasv()
+ f:epsv()
f:receive(gett)
f:quit()
return f:close()
end
local function sget(u)
- local gett = parse(u)
+ local gett = genericform(u)
local t = {}
gett.sink = ltn12.sink.table(t)
tget(gett)
diff --git a/src/http.lua b/src/http.lua
index d6bcc91..f2fff01 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -346,11 +346,13 @@ end
return 1, code, headers, status
end
-local function srequest(u, b)
+-- turns an url and a body into a generic request
+local function genericform(u, b)
local t = {}
local reqt = {
url = u,
- sink = ltn12.sink.table(t)
+ sink = ltn12.sink.table(t),
+ target = t
}
if b then
reqt.source = ltn12.source.string(b)
@@ -360,8 +362,15 @@ local function srequest(u, b)
}
reqt.method = "POST"
end
- local code, headers, status = socket.skip(1, trequest(reqt))
- return table.concat(t), code, headers, status
+ return reqt
+end
+
+_M.genericform = genericform
+
+local function srequest(u, b)
+ local reqt = genericform(u, b)
+ local _, code, headers, status = trequest(reqt)
+ return table.concat(reqt.target), code, headers, status
end
_M.request = socket.protect(function(reqt, body)
diff --git a/src/tp.lua b/src/tp.lua
index 328cbab..b8ebc56 100644
--- a/src/tp.lua
+++ b/src/tp.lua
@@ -46,6 +46,14 @@ end
-- metatable for sock object
local metat = { __index = {} }
+function metat.__index:getpeername()
+ return self.c:getpeername()
+end
+
+function metat.__index:getsockname()
+ return self.c:getpeername()
+end
+
function metat.__index:check(ok)
local code, reply = get_reply(self.c)
if not code then return nil, reply end
@@ -123,4 +131,4 @@ function _M.connect(host, port, timeout, create)
return base.setmetatable({c = c}, metat)
end
-return _M
\ No newline at end of file
+return _M
diff --git a/test/ftptest.lua b/test/ftptest.lua
index fb13326..3ea0d39 100644
--- a/test/ftptest.lua
+++ b/test/ftptest.lua
@@ -3,19 +3,31 @@ local ftp = require("socket.ftp")
local url = require("socket.url")
local ltn12 = require("ltn12")
+-- use dscl to create user "luasocket" with password "password"
+-- with home in /Users/diego/luasocket/test/ftp
+-- with group com.apple.access_ftp
+-- with shell set to /sbin/nologin
+-- set /etc/ftpchroot to chroot luasocket
+-- must set group com.apple.access_ftp on user _ftp (for anonymous access)
+-- copy index.html to /var/empty/pub (home of user ftp)
+-- start ftp server with
+-- sudo -s launchctl load -w /System/Library/LaunchDaemons/ftp.plist
+-- copy index.html to /Users/diego/luasocket/test/ftp
+-- stop with
+-- sudo -s launchctl unload -w /System/Library/LaunchDaemons/ftp.plist
+
-- override protection to make sure we see all errors
--socket.protect = function(s) return s end
dofile("testsupport.lua")
-local host, port, index_file, index, back, err, ret
+local host = host or "localhost"
+local port, index_file, index, back, err, ret
local t = socket.gettime()
-host = host or "localhost"
index_file = "index.html"
-
-- a function that returns a directory listing
local function nlst(u)
local t = {}
@@ -55,27 +67,27 @@ assert(not err and back == index, err)
print("ok")
io.write("erasing before upload: ")
-ret, err = dele("ftp://luasocket:pedrovian@" .. host .. "/index.up.html")
-if not ret then print(err)
+ret, err = dele("ftp://luasocket:password@" .. host .. "/index.up.html")
+if not ret then print(err)
else print("ok") end
io.write("testing upload: ")
-ret, err = ftp.put("ftp://luasocket:pedrovian@" .. host .. "/index.up.html;type=i", index)
+ret, err = ftp.put("ftp://luasocket:password@" .. host .. "/index.up.html;type=i", index)
assert(ret and not err, err)
print("ok")
io.write("downloading uploaded file: ")
-back, err = ftp.get("ftp://luasocket:pedrovian@" .. host .. "/index.up.html;type=i")
+back, err = ftp.get("ftp://luasocket:password@" .. host .. "/index.up.html;type=i")
assert(ret and not err and index == back, err)
print("ok")
io.write("erasing after upload/download: ")
-ret, err = dele("ftp://luasocket:pedrovian@" .. host .. "/index.up.html")
-assert(ret and not err, err)
+ret, err = dele("ftp://luasocket:password@" .. host .. "/index.up.html")
+assert(ret and not err, err)
print("ok")
io.write("testing weird-character translation: ")
-back, err = ftp.get("ftp://luasocket:pedrovian@" .. host .. "/%23%3f;type=i")
+back, err = ftp.get("ftp://luasocket:password@" .. host .. "/%23%3f;type=i")
assert(not err and back == index, err)
print("ok")
@@ -84,7 +96,7 @@ local back = {}
ret, err = ftp.get{
url = "//stupid:mistake@" .. host .. "/index.html",
user = "luasocket",
- password = "pedrovian",
+ password = "password",
type = "i",
sink = ltn12.sink.table(back)
}
--
cgit v1.2.3-55-g6feb
From aa1b8cc9bc35e56de15eeb153c899e4c51de82a8 Mon Sep 17 00:00:00 2001
From: enginix
Date: Fri, 24 Jun 2016 21:23:00 +0800
Subject: support datagram unix domain sockets
---
src/makefile | 2 +
src/unix.c | 328 ++-----------------------------------------
src/unixtcp.c | 338 ++++++++++++++++++++++++++++++++++++++++++++
src/unixtcp.h | 21 +++
src/unixudp.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/unixudp.h | 20 +++
test/unixclnt.lua | 8 --
test/unixsrvr.lua | 9 --
test/unixtcpclnt.lua | 8 ++
test/unixtcpsrvr.lua | 9 ++
test/unixudpclnt.lua | 9 ++
test/unixudpsrvr.lua | 9 ++
12 files changed, 818 insertions(+), 331 deletions(-)
create mode 100644 src/unixtcp.c
create mode 100644 src/unixtcp.h
create mode 100644 src/unixudp.c
create mode 100644 src/unixudp.h
delete mode 100644 test/unixclnt.lua
delete mode 100644 test/unixsrvr.lua
create mode 100644 test/unixtcpclnt.lua
create mode 100644 test/unixtcpsrvr.lua
create mode 100644 test/unixudpclnt.lua
create mode 100644 test/unixudpsrvr.lua
(limited to 'test')
diff --git a/src/makefile b/src/makefile
index 2e00950..0e4a544 100644
--- a/src/makefile
+++ b/src/makefile
@@ -307,6 +307,8 @@ UNIX_OBJS=\
timeout.$(O) \
io.$(O) \
usocket.$(O) \
+ unixtcp.$(O) \
+ unixudp.$(O) \
unix.$(O)
#------
diff --git a/src/unix.c b/src/unix.c
index 5bc3148..2009c19 100644
--- a/src/unix.c
+++ b/src/unix.c
@@ -2,329 +2,29 @@
* Unix domain socket
* LuaSocket toolkit
\*=========================================================================*/
-#include
-
#include "lua.h"
#include "lauxlib.h"
-#include "auxiliar.h"
-#include "socket.h"
-#include "options.h"
-#include "unix.h"
-#include
-
-/*=========================================================================*\
-* Internal function prototypes
-\*=========================================================================*/
-static int global_create(lua_State *L);
-static int meth_connect(lua_State *L);
-static int meth_listen(lua_State *L);
-static int meth_bind(lua_State *L);
-static int meth_send(lua_State *L);
-static int meth_shutdown(lua_State *L);
-static int meth_receive(lua_State *L);
-static int meth_accept(lua_State *L);
-static int meth_close(lua_State *L);
-static int meth_setoption(lua_State *L);
-static int meth_settimeout(lua_State *L);
-static int meth_getfd(lua_State *L);
-static int meth_setfd(lua_State *L);
-static int meth_dirty(lua_State *L);
-static int meth_getstats(lua_State *L);
-static int meth_setstats(lua_State *L);
-
-static const char *unix_tryconnect(p_unix un, const char *path);
-static const char *unix_trybind(p_unix un, const char *path);
-
-/* unix object methods */
-static luaL_Reg unix_methods[] = {
- {"__gc", meth_close},
- {"__tostring", auxiliar_tostring},
- {"accept", meth_accept},
- {"bind", meth_bind},
- {"close", meth_close},
- {"connect", meth_connect},
- {"dirty", meth_dirty},
- {"getfd", meth_getfd},
- {"getstats", meth_getstats},
- {"setstats", meth_setstats},
- {"listen", meth_listen},
- {"receive", meth_receive},
- {"send", meth_send},
- {"setfd", meth_setfd},
- {"setoption", meth_setoption},
- {"setpeername", meth_connect},
- {"setsockname", meth_bind},
- {"settimeout", meth_settimeout},
- {"shutdown", meth_shutdown},
- {NULL, NULL}
-};
-
-/* socket option handlers */
-static t_opt optset[] = {
- {"keepalive", opt_set_keepalive},
- {"reuseaddr", opt_set_reuseaddr},
- {"linger", opt_set_linger},
- {NULL, NULL}
-};
-
-/*-------------------------------------------------------------------------*\
-* Initializes module
-\*-------------------------------------------------------------------------*/
-int luaopen_socket_unix(lua_State *L) {
- /* create classes */
- auxiliar_newclass(L, "unix{master}", unix_methods);
- auxiliar_newclass(L, "unix{client}", unix_methods);
- auxiliar_newclass(L, "unix{server}", unix_methods);
- /* create class groups */
- auxiliar_add2group(L, "unix{master}", "unix{any}");
- auxiliar_add2group(L, "unix{client}", "unix{any}");
- auxiliar_add2group(L, "unix{server}", "unix{any}");
- /* return the function instead of the 'socket' table */
- lua_pushcfunction(L, global_create);
- return 1;
-}
-
-/*=========================================================================*\
-* Lua methods
-\*=========================================================================*/
-/*-------------------------------------------------------------------------*\
-* Just call buffered IO methods
-\*-------------------------------------------------------------------------*/
-static int meth_send(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
- return buffer_meth_send(L, &un->buf);
-}
-
-static int meth_receive(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
- return buffer_meth_receive(L, &un->buf);
-}
-
-static int meth_getstats(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
- return buffer_meth_getstats(L, &un->buf);
-}
-
-static int meth_setstats(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
- return buffer_meth_setstats(L, &un->buf);
-}
-
-/*-------------------------------------------------------------------------*\
-* Just call option handler
-\*-------------------------------------------------------------------------*/
-static int meth_setoption(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
- return opt_meth_setoption(L, optset, &un->sock);
-}
-
-/*-------------------------------------------------------------------------*\
-* Select support methods
-\*-------------------------------------------------------------------------*/
-static int meth_getfd(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
- lua_pushnumber(L, (int) un->sock);
- return 1;
-}
-
-/* this is very dangerous, but can be handy for those that are brave enough */
-static int meth_setfd(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
- un->sock = (t_socket) luaL_checknumber(L, 2);
- return 0;
-}
-
-static int meth_dirty(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
- lua_pushboolean(L, !buffer_isempty(&un->buf));
- return 1;
-}
+#include "unixtcp.h"
+#include "unixudp.h"
/*-------------------------------------------------------------------------*\
-* Waits for and returns a client object attempting connection to the
-* server object
+* Modules and functions
\*-------------------------------------------------------------------------*/
-static int meth_accept(lua_State *L) {
- p_unix server = (p_unix) auxiliar_checkclass(L, "unix{server}", 1);
- p_timeout tm = timeout_markstart(&server->tm);
- t_socket sock;
- int err = socket_accept(&server->sock, &sock, NULL, NULL, tm);
- /* if successful, push client socket */
- if (err == IO_DONE) {
- p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix));
- auxiliar_setclass(L, "unix{client}", -1);
- /* initialize structure fields */
- socket_setnonblocking(&sock);
- clnt->sock = sock;
- io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
- (p_error) socket_ioerror, &clnt->sock);
- timeout_init(&clnt->tm, -1, -1);
- buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
- return 1;
- } else {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(err));
- return 2;
- }
-}
-
-/*-------------------------------------------------------------------------*\
-* Binds an object to an address
-\*-------------------------------------------------------------------------*/
-static const char *unix_trybind(p_unix un, const char *path) {
- struct sockaddr_un local;
- size_t len = strlen(path);
- int err;
- if (len >= sizeof(local.sun_path)) return "path too long";
- memset(&local, 0, sizeof(local));
- strcpy(local.sun_path, path);
- local.sun_family = AF_UNIX;
-#ifdef UNIX_HAS_SUN_LEN
- local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
- + len + 1;
- err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
-
-#else
- err = socket_bind(&un->sock, (SA *) &local,
- sizeof(local.sun_family) + len);
-#endif
- if (err != IO_DONE) socket_destroy(&un->sock);
- return socket_strerror(err);
-}
-
-static int meth_bind(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1);
- const char *path = luaL_checkstring(L, 2);
- const char *err = unix_trybind(un, path);
- if (err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Turns a master unix object into a client object.
-\*-------------------------------------------------------------------------*/
-static const char *unix_tryconnect(p_unix un, const char *path)
-{
- struct sockaddr_un remote;
- int err;
- size_t len = strlen(path);
- if (len >= sizeof(remote.sun_path)) return "path too long";
- memset(&remote, 0, sizeof(remote));
- strcpy(remote.sun_path, path);
- remote.sun_family = AF_UNIX;
- timeout_markstart(&un->tm);
-#ifdef UNIX_HAS_SUN_LEN
- remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
- + len + 1;
- err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
-#else
- err = socket_connect(&un->sock, (SA *) &remote,
- sizeof(remote.sun_family) + len, &un->tm);
-#endif
- if (err != IO_DONE) socket_destroy(&un->sock);
- return socket_strerror(err);
-}
-
-static int meth_connect(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1);
- const char *path = luaL_checkstring(L, 2);
- const char *err = unix_tryconnect(un, path);
- if (err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- /* turn master object into a client object */
- auxiliar_setclass(L, "unix{client}", 1);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Closes socket used by object
-\*-------------------------------------------------------------------------*/
-static int meth_close(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
- socket_destroy(&un->sock);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Puts the sockt in listen mode
-\*-------------------------------------------------------------------------*/
-static int meth_listen(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1);
- int backlog = (int) luaL_optnumber(L, 2, 32);
- int err = socket_listen(&un->sock, backlog);
- if (err != IO_DONE) {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(err));
- return 2;
- }
- /* turn master object into a server object */
- auxiliar_setclass(L, "unix{server}", 1);
- lua_pushnumber(L, 1);
- return 1;
-}
+static const luaL_Reg mod[] = {
+ {"tcp", unixtcp_open},
+ {"udp", unixudp_open},
+ {NULL, NULL}
+};
/*-------------------------------------------------------------------------*\
-* Shuts the connection down partially
+* Initializes module
\*-------------------------------------------------------------------------*/
-static int meth_shutdown(lua_State *L)
+int luaopen_socket_unix(lua_State *L)
{
- /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
- static const char* methods[] = { "receive", "send", "both", NULL };
- p_unix tcp = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
- int how = luaL_checkoption(L, 2, "both", methods);
- socket_shutdown(&tcp->sock, how);
- lua_pushnumber(L, 1);
- return 1;
+ int i;
+ lua_newtable(L);
+ for (i = 0; mod[i].name; i++) mod[i].func(L);
+ return 1;
}
-/*-------------------------------------------------------------------------*\
-* Just call tm methods
-\*-------------------------------------------------------------------------*/
-static int meth_settimeout(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
- return timeout_meth_settimeout(L, &un->tm);
-}
-
-/*=========================================================================*\
-* Library functions
-\*=========================================================================*/
-/*-------------------------------------------------------------------------*\
-* Creates a master unix object
-\*-------------------------------------------------------------------------*/
-static int global_create(lua_State *L) {
- t_socket sock;
- int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
- /* try to allocate a system socket */
- if (err == IO_DONE) {
- /* allocate unix object */
- p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
- /* set its type as master object */
- auxiliar_setclass(L, "unix{master}", -1);
- /* initialize remaining structure fields */
- socket_setnonblocking(&sock);
- un->sock = sock;
- io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
- (p_error) socket_ioerror, &un->sock);
- timeout_init(&un->tm, -1, -1);
- buffer_init(&un->buf, &un->io, &un->tm);
- return 1;
- } else {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(err));
- return 2;
- }
-}
diff --git a/src/unixtcp.c b/src/unixtcp.c
new file mode 100644
index 0000000..88baac0
--- /dev/null
+++ b/src/unixtcp.c
@@ -0,0 +1,338 @@
+/*=========================================================================*\
+* Unix domain socket tcp sub module
+* LuaSocket toolkit
+\*=========================================================================*/
+#include
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "auxiliar.h"
+#include "socket.h"
+#include "options.h"
+#include "unixtcp.h"
+#include
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int global_create(lua_State *L);
+static int meth_connect(lua_State *L);
+static int meth_listen(lua_State *L);
+static int meth_bind(lua_State *L);
+static int meth_send(lua_State *L);
+static int meth_shutdown(lua_State *L);
+static int meth_receive(lua_State *L);
+static int meth_accept(lua_State *L);
+static int meth_close(lua_State *L);
+static int meth_setoption(lua_State *L);
+static int meth_settimeout(lua_State *L);
+static int meth_getfd(lua_State *L);
+static int meth_setfd(lua_State *L);
+static int meth_dirty(lua_State *L);
+static int meth_getstats(lua_State *L);
+static int meth_setstats(lua_State *L);
+
+static const char *unixtcp_tryconnect(p_unix un, const char *path);
+static const char *unixtcp_trybind(p_unix un, const char *path);
+
+/* unixtcp object methods */
+static luaL_Reg unixtcp_methods[] = {
+ {"__gc", meth_close},
+ {"__tostring", auxiliar_tostring},
+ {"accept", meth_accept},
+ {"bind", meth_bind},
+ {"close", meth_close},
+ {"connect", meth_connect},
+ {"dirty", meth_dirty},
+ {"getfd", meth_getfd},
+ {"getstats", meth_getstats},
+ {"setstats", meth_setstats},
+ {"listen", meth_listen},
+ {"receive", meth_receive},
+ {"send", meth_send},
+ {"setfd", meth_setfd},
+ {"setoption", meth_setoption},
+ {"setpeername", meth_connect},
+ {"setsockname", meth_bind},
+ {"settimeout", meth_settimeout},
+ {"shutdown", meth_shutdown},
+ {NULL, NULL}
+};
+
+/* socket option handlers */
+static t_opt optset[] = {
+ {"keepalive", opt_set_keepalive},
+ {"reuseaddr", opt_set_reuseaddr},
+ {"linger", opt_set_linger},
+ {NULL, NULL}
+};
+
+/* functions in library namespace */
+static luaL_Reg func[] = {
+ {"tcp", global_create},
+ {NULL, NULL}
+};
+
+/*-------------------------------------------------------------------------*\
+* Initializes module
+\*-------------------------------------------------------------------------*/
+int unixtcp_open(lua_State *L)
+{
+ /* create classes */
+ auxiliar_newclass(L, "unixtcp{master}", unixtcp_methods);
+ auxiliar_newclass(L, "unixtcp{client}", unixtcp_methods);
+ auxiliar_newclass(L, "unixtcp{server}", unixtcp_methods);
+
+ /* create class groups */
+ auxiliar_add2group(L, "unixtcp{master}", "unixtcp{any}");
+ auxiliar_add2group(L, "unixtcp{client}", "unixtcp{any}");
+ auxiliar_add2group(L, "unixtcp{server}", "unixtcp{any}");
+
+ luaL_setfuncs(L, func, 0);
+ return 1;
+}
+
+/*=========================================================================*\
+* Lua methods
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Just call buffered IO methods
+\*-------------------------------------------------------------------------*/
+static int meth_send(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
+ return buffer_meth_send(L, &un->buf);
+}
+
+static int meth_receive(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
+ return buffer_meth_receive(L, &un->buf);
+}
+
+static int meth_getstats(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
+ return buffer_meth_getstats(L, &un->buf);
+}
+
+static int meth_setstats(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
+ return buffer_meth_setstats(L, &un->buf);
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call option handler
+\*-------------------------------------------------------------------------*/
+static int meth_setoption(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
+ return opt_meth_setoption(L, optset, &un->sock);
+}
+
+/*-------------------------------------------------------------------------*\
+* Select support methods
+\*-------------------------------------------------------------------------*/
+static int meth_getfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
+ lua_pushnumber(L, (int) un->sock);
+ return 1;
+}
+
+/* this is very dangerous, but can be handy for those that are brave enough */
+static int meth_setfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
+ un->sock = (t_socket) luaL_checknumber(L, 2);
+ return 0;
+}
+
+static int meth_dirty(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
+ lua_pushboolean(L, !buffer_isempty(&un->buf));
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Waits for and returns a client object attempting connection to the
+* server object
+\*-------------------------------------------------------------------------*/
+static int meth_accept(lua_State *L) {
+ p_unix server = (p_unix) auxiliar_checkclass(L, "unixtcp{server}", 1);
+ p_timeout tm = timeout_markstart(&server->tm);
+ t_socket sock;
+ int err = socket_accept(&server->sock, &sock, NULL, NULL, tm);
+ /* if successful, push client socket */
+ if (err == IO_DONE) {
+ p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix));
+ auxiliar_setclass(L, "unixtcp{client}", -1);
+ /* initialize structure fields */
+ socket_setnonblocking(&sock);
+ clnt->sock = sock;
+ io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
+ (p_error) socket_ioerror, &clnt->sock);
+ timeout_init(&clnt->tm, -1, -1);
+ buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
+ return 1;
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+}
+
+/*-------------------------------------------------------------------------*\
+* Binds an object to an address
+\*-------------------------------------------------------------------------*/
+static const char *unixtcp_trybind(p_unix un, const char *path) {
+ struct sockaddr_un local;
+ size_t len = strlen(path);
+ int err;
+ if (len >= sizeof(local.sun_path)) return "path too long";
+ memset(&local, 0, sizeof(local));
+ strcpy(local.sun_path, path);
+ local.sun_family = AF_UNIX;
+#ifdef UNIX_HAS_SUN_LEN
+ local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
+ + len + 1;
+ err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
+
+#else
+ err = socket_bind(&un->sock, (SA *) &local,
+ sizeof(local.sun_family) + len);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_bind(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{master}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixtcp_trybind(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Turns a master unixtcp object into a client object.
+\*-------------------------------------------------------------------------*/
+static const char *unixtcp_tryconnect(p_unix un, const char *path)
+{
+ struct sockaddr_un remote;
+ int err;
+ size_t len = strlen(path);
+ if (len >= sizeof(remote.sun_path)) return "path too long";
+ memset(&remote, 0, sizeof(remote));
+ strcpy(remote.sun_path, path);
+ remote.sun_family = AF_UNIX;
+ timeout_markstart(&un->tm);
+#ifdef UNIX_HAS_SUN_LEN
+ remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ + len + 1;
+ err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
+#else
+ err = socket_connect(&un->sock, (SA *) &remote,
+ sizeof(remote.sun_family) + len, &un->tm);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_connect(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{master}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixtcp_tryconnect(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ /* turn master object into a client object */
+ auxiliar_setclass(L, "unixtcp{client}", 1);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Closes socket used by object
+\*-------------------------------------------------------------------------*/
+static int meth_close(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
+ socket_destroy(&un->sock);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Puts the sockt in listen mode
+\*-------------------------------------------------------------------------*/
+static int meth_listen(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{master}", 1);
+ int backlog = (int) luaL_optnumber(L, 2, 32);
+ int err = socket_listen(&un->sock, backlog);
+ if (err != IO_DONE) {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+ /* turn master object into a server object */
+ auxiliar_setclass(L, "unixtcp{server}", 1);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Shuts the connection down partially
+\*-------------------------------------------------------------------------*/
+static int meth_shutdown(lua_State *L)
+{
+ /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
+ static const char* methods[] = { "receive", "send", "both", NULL };
+ p_unix tcp = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
+ int how = luaL_checkoption(L, 2, "both", methods);
+ socket_shutdown(&tcp->sock, how);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call tm methods
+\*-------------------------------------------------------------------------*/
+static int meth_settimeout(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
+ return timeout_meth_settimeout(L, &un->tm);
+}
+
+/*=========================================================================*\
+* Library functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Creates a master unixtcp object
+\*-------------------------------------------------------------------------*/
+static int global_create(lua_State *L) {
+ t_socket sock;
+ int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
+ /* try to allocate a system socket */
+ if (err == IO_DONE) {
+ /* allocate unixtcp object */
+ p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
+ /* set its type as master object */
+ auxiliar_setclass(L, "unixtcp{master}", -1);
+ /* initialize remaining structure fields */
+ socket_setnonblocking(&sock);
+ un->sock = sock;
+ io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
+ (p_error) socket_ioerror, &un->sock);
+ timeout_init(&un->tm, -1, -1);
+ buffer_init(&un->buf, &un->io, &un->tm);
+ return 1;
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+}
diff --git a/src/unixtcp.h b/src/unixtcp.h
new file mode 100644
index 0000000..0eababc
--- /dev/null
+++ b/src/unixtcp.h
@@ -0,0 +1,21 @@
+#ifndef UNIXTCP_H
+#define UNIXTCP_H
+/*=========================================================================*\
+* UNIX TCP object
+* LuaSocket toolkit
+*
+* The unixtcp.h module is basicly a glue that puts together modules buffer.h,
+* timeout.h socket.h and inet.h to provide the LuaSocket UNIX TCP (AF_UNIX,
+* SOCK_STREAM) support.
+*
+* Three classes are defined: master, client and server. The master class is
+* a newly created unixtcp object, that has not been bound or connected. Server
+* objects are unixtcp objects bound to some local address. Client objects are
+* unixtcp objects either connected to some address or returned by the accept
+* method of a server object.
+\*=========================================================================*/
+#include "unix.h"
+
+int unixtcp_open(lua_State *L);
+
+#endif /* UNIXTCP_H */
diff --git a/src/unixudp.c b/src/unixudp.c
new file mode 100644
index 0000000..ec348cf
--- /dev/null
+++ b/src/unixudp.c
@@ -0,0 +1,388 @@
+/*=========================================================================*\
+* Unix domain socket udp submodule
+* LuaSocket toolkit
+\*=========================================================================*/
+#include
+#include
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "auxiliar.h"
+#include "socket.h"
+#include "options.h"
+#include "unix.h"
+#include
+
+#define UNIXUDP_DATAGRAMSIZE 8192
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int global_create(lua_State *L);
+static int meth_connect(lua_State *L);
+static int meth_bind(lua_State *L);
+static int meth_send(lua_State *L);
+static int meth_receive(lua_State *L);
+static int meth_close(lua_State *L);
+static int meth_setoption(lua_State *L);
+static int meth_settimeout(lua_State *L);
+static int meth_gettimeout(lua_State *L);
+static int meth_getfd(lua_State *L);
+static int meth_setfd(lua_State *L);
+static int meth_dirty(lua_State *L);
+static int meth_receivefrom(lua_State *L);
+static int meth_sendto(lua_State *L);
+
+static const char *unixudp_tryconnect(p_unix un, const char *path);
+static const char *unixudp_trybind(p_unix un, const char *path);
+
+/* unixudp object methods */
+static luaL_Reg unixudp_methods[] = {
+ {"__gc", meth_close},
+ {"__tostring", auxiliar_tostring},
+ {"bind", meth_bind},
+ {"close", meth_close},
+ {"connect", meth_connect},
+ {"dirty", meth_dirty},
+ {"getfd", meth_getfd},
+ {"send", meth_send},
+ {"sendto", meth_sendto},
+ {"receive", meth_receive},
+ {"receivefrom", meth_receivefrom},
+ {"setfd", meth_setfd},
+ {"setoption", meth_setoption},
+ {"setpeername", meth_connect},
+ {"setsockname", meth_bind},
+ {"settimeout", meth_settimeout},
+ {"gettimeout", meth_gettimeout},
+ {NULL, NULL}
+};
+
+/* socket option handlers */
+static t_opt optset[] = {
+ {"reuseaddr", opt_set_reuseaddr},
+ {NULL, NULL}
+};
+
+/* functions in library namespace */
+static luaL_Reg func[] = {
+ {"udp", global_create},
+ {NULL, NULL}
+};
+
+/*-------------------------------------------------------------------------*\
+* Initializes module
+\*-------------------------------------------------------------------------*/
+int unixudp_open(lua_State *L)
+{
+ /* create classes */
+ auxiliar_newclass(L, "unixudp{connected}", unixudp_methods);
+ auxiliar_newclass(L, "unixudp{unconnected}", unixudp_methods);
+ /* create class groups */
+ auxiliar_add2group(L, "unixudp{connected}", "unixudp{any}");
+ auxiliar_add2group(L, "unixudp{unconnected}", "unixudp{any}");
+ auxiliar_add2group(L, "unixudp{connected}", "select{able}");
+ auxiliar_add2group(L, "unixudp{unconnected}", "select{able}");
+
+ luaL_setfuncs(L, func, 0);
+ return 1;
+}
+
+/*=========================================================================*\
+* Lua methods
+\*=========================================================================*/
+static const char *unixudp_strerror(int err)
+{
+ /* a 'closed' error on an unconnected means the target address was not
+ * accepted by the transport layer */
+ if (err == IO_CLOSED) return "refused";
+ else return socket_strerror(err);
+}
+
+static int meth_send(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{connected}", 1);
+ p_timeout tm = &un->tm;
+ size_t count, sent = 0;
+ int err;
+ const char *data = luaL_checklstring(L, 2, &count);
+ timeout_markstart(tm);
+ err = socket_send(&un->sock, data, count, &sent, tm);
+ if (err != IO_DONE) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixudp_strerror(err));
+ return 2;
+ }
+ lua_pushnumber(L, (lua_Number) sent);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Send data through unconnected unixudp socket
+\*-------------------------------------------------------------------------*/
+static int meth_sendto(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{unconnected}", 1);
+ size_t count, sent = 0;
+ const char *data = luaL_checklstring(L, 2, &count);
+ const char *path = luaL_checkstring(L, 3);
+ p_timeout tm = &un->tm;
+ int err;
+ struct sockaddr_un remote;
+ size_t len = strlen(path);
+
+ if (len >= sizeof(remote.sun_path)) {
+ lua_pushnil(L);
+ lua_pushstring(L, "path too long");
+ return 2;
+ }
+
+ memset(&remote, 0, sizeof(remote));
+ strcpy(remote.sun_path, path);
+ remote.sun_family = AF_UNIX;
+ timeout_markstart(tm);
+#ifdef UNIX_HAS_SUN_LEN
+ remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ + len + 1;
+ err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, remote.sun_len, tm);
+#else
+ err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote,
+ sizeof(remote.sun_family) + len, tm);
+#endif
+ if (err != IO_DONE) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixudp_strerror(err));
+ return 2;
+ }
+ lua_pushnumber(L, (lua_Number) sent);
+ return 1;
+}
+
+static int meth_receive(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{any}", 1);
+ char buf[UNIXUDP_DATAGRAMSIZE];
+ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
+ int err;
+ p_timeout tm = &un->tm;
+ timeout_markstart(tm);
+ if (!dgram) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "out of memory");
+ return 2;
+ }
+ err = socket_recv(&un->sock, dgram, wanted, &got, tm);
+ /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
+ if (err != IO_DONE && err != IO_CLOSED) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixudp_strerror(err));
+ if (wanted > sizeof(buf)) free(dgram);
+ return 2;
+ }
+ lua_pushlstring(L, dgram, got);
+ if (wanted > sizeof(buf)) free(dgram);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Receives data and sender from a UDP socket
+\*-------------------------------------------------------------------------*/
+static int meth_receivefrom(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{unconnected}", 1);
+ char buf[UNIXUDP_DATAGRAMSIZE];
+ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
+ struct sockaddr_un addr;
+ socklen_t addr_len = sizeof(addr);
+ int err;
+ p_timeout tm = &un->tm;
+ timeout_markstart(tm);
+ if (!dgram) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "out of memory");
+ return 2;
+ }
+ err = socket_recvfrom(&un->sock, dgram, wanted, &got, (SA *) &addr,
+ &addr_len, tm);
+ /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
+ if (err != IO_DONE && err != IO_CLOSED) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixudp_strerror(err));
+ if (wanted > sizeof(buf)) free(dgram);
+ return 2;
+ }
+
+ lua_pushlstring(L, dgram, got);
+ /* the path may be empty, when client send without bind */
+ lua_pushstring(L, addr.sun_path);
+ if (wanted > sizeof(buf)) free(dgram);
+ return 2;
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call option handler
+\*-------------------------------------------------------------------------*/
+static int meth_setoption(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
+ return opt_meth_setoption(L, optset, &un->sock);
+}
+
+/*-------------------------------------------------------------------------*\
+* Select support methods
+\*-------------------------------------------------------------------------*/
+static int meth_getfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
+ lua_pushnumber(L, (int) un->sock);
+ return 1;
+}
+
+/* this is very dangerous, but can be handy for those that are brave enough */
+static int meth_setfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
+ un->sock = (t_socket) luaL_checknumber(L, 2);
+ return 0;
+}
+
+static int meth_dirty(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
+ (void) un;
+ lua_pushboolean(L, 0);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Binds an object to an address
+\*-------------------------------------------------------------------------*/
+static const char *unixudp_trybind(p_unix un, const char *path) {
+ struct sockaddr_un local;
+ size_t len = strlen(path);
+ int err;
+ if (len >= sizeof(local.sun_path)) return "path too long";
+ memset(&local, 0, sizeof(local));
+ strcpy(local.sun_path, path);
+ local.sun_family = AF_UNIX;
+#ifdef UNIX_HAS_SUN_LEN
+ local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
+ + len + 1;
+ err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
+
+#else
+ err = socket_bind(&un->sock, (SA *) &local,
+ sizeof(local.sun_family) + len);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_bind(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{unconnected}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixudp_trybind(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Turns a master unixudp object into a client object.
+\*-------------------------------------------------------------------------*/
+static const char *unixudp_tryconnect(p_unix un, const char *path)
+{
+ struct sockaddr_un remote;
+ int err;
+ size_t len = strlen(path);
+ if (len >= sizeof(remote.sun_path)) return "path too long";
+ memset(&remote, 0, sizeof(remote));
+ strcpy(remote.sun_path, path);
+ remote.sun_family = AF_UNIX;
+ timeout_markstart(&un->tm);
+#ifdef UNIX_HAS_SUN_LEN
+ remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ + len + 1;
+ err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
+#else
+ err = socket_connect(&un->sock, (SA *) &remote,
+ sizeof(remote.sun_family) + len, &un->tm);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_connect(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{any}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixudp_tryconnect(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ /* turn unconnected object into a connected object */
+ auxiliar_setclass(L, "unixudp{connected}", 1);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Closes socket used by object
+\*-------------------------------------------------------------------------*/
+static int meth_close(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
+ socket_destroy(&un->sock);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call tm methods
+\*-------------------------------------------------------------------------*/
+static int meth_settimeout(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
+ return timeout_meth_settimeout(L, &un->tm);
+}
+
+static int meth_gettimeout(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
+ return timeout_meth_gettimeout(L, &un->tm);
+}
+
+/*=========================================================================*\
+* Library functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Creates a master unixudp object
+\*-------------------------------------------------------------------------*/
+static int global_create(lua_State *L)
+{
+ t_socket sock;
+ int err = socket_create(&sock, AF_UNIX, SOCK_DGRAM, 0);
+ /* try to allocate a system socket */
+ if (err == IO_DONE) {
+ /* allocate unixudp object */
+ p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
+ /* set its type as master object */
+ auxiliar_setclass(L, "unixudp{unconnected}", -1);
+ /* initialize remaining structure fields */
+ socket_setnonblocking(&sock);
+ un->sock = sock;
+ io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
+ (p_error) socket_ioerror, &un->sock);
+ timeout_init(&un->tm, -1, -1);
+ buffer_init(&un->buf, &un->io, &un->tm);
+ return 1;
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+}
diff --git a/src/unixudp.h b/src/unixudp.h
new file mode 100644
index 0000000..ccfdc07
--- /dev/null
+++ b/src/unixudp.h
@@ -0,0 +1,20 @@
+#ifndef UNIXUDP_H
+#define UNIXUDP_H
+/*=========================================================================*\
+* UDP object
+* LuaSocket toolkit
+*
+* The udp.h module provides LuaSocket with support for UDP protocol
+* (AF_INET, SOCK_DGRAM).
+*
+* Two classes are defined: connected and unconnected. UDP objects are
+* originally unconnected. They can be "connected" to a given address
+* with a call to the setpeername function. The same function can be used to
+* break the connection.
+\*=========================================================================*/
+
+#include "unix.h"
+
+int unixudp_open(lua_State *L);
+
+#endif /* UNIXUDP_H */
diff --git a/test/unixclnt.lua b/test/unixclnt.lua
deleted file mode 100644
index 5171535..0000000
--- a/test/unixclnt.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-socket = require"socket"
-socket.unix = require"socket.unix"
-c = assert(socket.unix())
-assert(c:connect("/tmp/foo"))
-while 1 do
- local l = io.read()
- assert(c:send(l .. "\n"))
-end
diff --git a/test/unixsrvr.lua b/test/unixsrvr.lua
deleted file mode 100644
index 81b9c99..0000000
--- a/test/unixsrvr.lua
+++ /dev/null
@@ -1,9 +0,0 @@
- socket = require"socket"
- socket.unix = require"socket.unix"
- u = assert(socket.unix())
- assert(u:bind("/tmp/foo"))
- assert(u:listen())
- c = assert(u:accept())
- while 1 do
- print(assert(c:receive()))
- end
diff --git a/test/unixtcpclnt.lua b/test/unixtcpclnt.lua
new file mode 100644
index 0000000..652a680
--- /dev/null
+++ b/test/unixtcpclnt.lua
@@ -0,0 +1,8 @@
+socket = require"socket"
+socket.unix = require"socket.unix"
+c = assert(socket.unix.tcp())
+assert(c:connect("/tmp/foo"))
+while 1 do
+ local l = io.read()
+ assert(c:send(l .. "\n"))
+end
diff --git a/test/unixtcpsrvr.lua b/test/unixtcpsrvr.lua
new file mode 100644
index 0000000..2a2b065
--- /dev/null
+++ b/test/unixtcpsrvr.lua
@@ -0,0 +1,9 @@
+ socket = require"socket"
+ socket.unix = require"socket.unix"
+ u = assert(socket.unix.tcp())
+ assert(u:bind("/tmp/foo"))
+ assert(u:listen())
+ c = assert(u:accept())
+ while 1 do
+ print(assert(c:receive()))
+ end
diff --git a/test/unixudpclnt.lua b/test/unixudpclnt.lua
new file mode 100644
index 0000000..bbbff7f
--- /dev/null
+++ b/test/unixudpclnt.lua
@@ -0,0 +1,9 @@
+socket = require"socket"
+socket.unix = require"socket.unix"
+c = assert(socket.unix.udp())
+c:bind("/tmp/bar")
+while 1 do
+ local l = io.read("*l")
+ assert(c:sendto(l, "/tmp/foo"))
+ print(assert(c:receivefrom()))
+end
diff --git a/test/unixudpsrvr.lua b/test/unixudpsrvr.lua
new file mode 100644
index 0000000..5ed71dc
--- /dev/null
+++ b/test/unixudpsrvr.lua
@@ -0,0 +1,9 @@
+ socket = require"socket"
+ socket.unix = require"socket.unix"
+ u = assert(socket.unix.udp())
+ assert(u:bind("/tmp/foo"))
+ while 1 do
+ x, r = assert(u:receivefrom())
+ print(x, r)
+ assert(u:sendto(">" .. x, r))
+ end
--
cgit v1.2.3-55-g6feb
From 3a33c37b9ce852d0b3531e82c6ffdb47bb937f0a Mon Sep 17 00:00:00 2001
From: enginix
Date: Sun, 25 Dec 2016 23:15:12 +0800
Subject: rename unix.tcp to unix.stream, unix.udp to unix.dgram
---
src/makefile | 4 +-
src/unix.c | 8 +-
src/unixdgram.c | 407 ++++++++++++++++++++++++++++++++++++++++++++++++
src/unixdgram.h | 20 +++
src/unixstream.c | 357 ++++++++++++++++++++++++++++++++++++++++++
src/unixstream.h | 21 +++
src/unixtcp.c | 357 ------------------------------------------
src/unixtcp.h | 21 ---
src/unixudp.c | 407 ------------------------------------------------
src/unixudp.h | 20 ---
test/unixdgramclnt.lua | 9 ++
test/unixdgramsrvr.lua | 9 ++
test/unixstreamclnt.lua | 8 +
test/unixstreamsrvr.lua | 9 ++
test/unixtcpclnt.lua | 8 -
test/unixtcpsrvr.lua | 9 --
test/unixudpclnt.lua | 9 --
test/unixudpsrvr.lua | 9 --
18 files changed, 846 insertions(+), 846 deletions(-)
create mode 100644 src/unixdgram.c
create mode 100644 src/unixdgram.h
create mode 100644 src/unixstream.c
create mode 100644 src/unixstream.h
delete mode 100644 src/unixtcp.c
delete mode 100644 src/unixtcp.h
delete mode 100644 src/unixudp.c
delete mode 100644 src/unixudp.h
create mode 100644 test/unixdgramclnt.lua
create mode 100644 test/unixdgramsrvr.lua
create mode 100644 test/unixstreamclnt.lua
create mode 100644 test/unixstreamsrvr.lua
delete mode 100644 test/unixtcpclnt.lua
delete mode 100644 test/unixtcpsrvr.lua
delete mode 100644 test/unixudpclnt.lua
delete mode 100644 test/unixudpsrvr.lua
(limited to 'test')
diff --git a/src/makefile b/src/makefile
index 2dfe549..494baab 100644
--- a/src/makefile
+++ b/src/makefile
@@ -307,8 +307,8 @@ UNIX_OBJS=\
timeout.$(O) \
io.$(O) \
usocket.$(O) \
- unixtcp.$(O) \
- unixudp.$(O) \
+ unixstream.$(O) \
+ unixdgram.$(O) \
compat.$(O) \
unix.$(O)
diff --git a/src/unix.c b/src/unix.c
index 2009c19..e604733 100644
--- a/src/unix.c
+++ b/src/unix.c
@@ -5,15 +5,15 @@
#include "lua.h"
#include "lauxlib.h"
-#include "unixtcp.h"
-#include "unixudp.h"
+#include "unixstream.h"
+#include "unixdgram.h"
/*-------------------------------------------------------------------------*\
* Modules and functions
\*-------------------------------------------------------------------------*/
static const luaL_Reg mod[] = {
- {"tcp", unixtcp_open},
- {"udp", unixudp_open},
+ {"stream", unixstream_open},
+ {"dgram", unixdgram_open},
{NULL, NULL}
};
diff --git a/src/unixdgram.c b/src/unixdgram.c
new file mode 100644
index 0000000..c07cbd5
--- /dev/null
+++ b/src/unixdgram.c
@@ -0,0 +1,407 @@
+/*=========================================================================*\
+* Unix domain socket dgram submodule
+* LuaSocket toolkit
+\*=========================================================================*/
+#include
+#include
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "compat.h"
+
+#include "auxiliar.h"
+#include "socket.h"
+#include "options.h"
+#include "unix.h"
+#include
+
+#define UNIXDGRAM_DATAGRAMSIZE 8192
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int global_create(lua_State *L);
+static int meth_connect(lua_State *L);
+static int meth_bind(lua_State *L);
+static int meth_send(lua_State *L);
+static int meth_receive(lua_State *L);
+static int meth_close(lua_State *L);
+static int meth_setoption(lua_State *L);
+static int meth_settimeout(lua_State *L);
+static int meth_gettimeout(lua_State *L);
+static int meth_getfd(lua_State *L);
+static int meth_setfd(lua_State *L);
+static int meth_dirty(lua_State *L);
+static int meth_receivefrom(lua_State *L);
+static int meth_sendto(lua_State *L);
+static int meth_getsockname(lua_State *L);
+
+static const char *unixdgram_tryconnect(p_unix un, const char *path);
+static const char *unixdgram_trybind(p_unix un, const char *path);
+
+/* unixdgram object methods */
+static luaL_Reg unixdgram_methods[] = {
+ {"__gc", meth_close},
+ {"__tostring", auxiliar_tostring},
+ {"bind", meth_bind},
+ {"close", meth_close},
+ {"connect", meth_connect},
+ {"dirty", meth_dirty},
+ {"getfd", meth_getfd},
+ {"send", meth_send},
+ {"sendto", meth_sendto},
+ {"receive", meth_receive},
+ {"receivefrom", meth_receivefrom},
+ {"setfd", meth_setfd},
+ {"setoption", meth_setoption},
+ {"setpeername", meth_connect},
+ {"setsockname", meth_bind},
+ {"getsockname", meth_getsockname},
+ {"settimeout", meth_settimeout},
+ {"gettimeout", meth_gettimeout},
+ {NULL, NULL}
+};
+
+/* socket option handlers */
+static t_opt optset[] = {
+ {"reuseaddr", opt_set_reuseaddr},
+ {NULL, NULL}
+};
+
+/* functions in library namespace */
+static luaL_Reg func[] = {
+ {"dgram", global_create},
+ {NULL, NULL}
+};
+
+/*-------------------------------------------------------------------------*\
+* Initializes module
+\*-------------------------------------------------------------------------*/
+int unixdgram_open(lua_State *L)
+{
+ /* create classes */
+ auxiliar_newclass(L, "unixdgram{connected}", unixdgram_methods);
+ auxiliar_newclass(L, "unixdgram{unconnected}", unixdgram_methods);
+ /* create class groups */
+ auxiliar_add2group(L, "unixdgram{connected}", "unixdgram{any}");
+ auxiliar_add2group(L, "unixdgram{unconnected}", "unixdgram{any}");
+ auxiliar_add2group(L, "unixdgram{connected}", "select{able}");
+ auxiliar_add2group(L, "unixdgram{unconnected}", "select{able}");
+
+ luaL_setfuncs(L, func, 0);
+ return 0;
+}
+
+/*=========================================================================*\
+* Lua methods
+\*=========================================================================*/
+static const char *unixdgram_strerror(int err)
+{
+ /* a 'closed' error on an unconnected means the target address was not
+ * accepted by the transport layer */
+ if (err == IO_CLOSED) return "refused";
+ else return socket_strerror(err);
+}
+
+static int meth_send(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{connected}", 1);
+ p_timeout tm = &un->tm;
+ size_t count, sent = 0;
+ int err;
+ const char *data = luaL_checklstring(L, 2, &count);
+ timeout_markstart(tm);
+ err = socket_send(&un->sock, data, count, &sent, tm);
+ if (err != IO_DONE) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixdgram_strerror(err));
+ return 2;
+ }
+ lua_pushnumber(L, (lua_Number) sent);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Send data through unconnected unixdgram socket
+\*-------------------------------------------------------------------------*/
+static int meth_sendto(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
+ size_t count, sent = 0;
+ const char *data = luaL_checklstring(L, 2, &count);
+ const char *path = luaL_checkstring(L, 3);
+ p_timeout tm = &un->tm;
+ int err;
+ struct sockaddr_un remote;
+ size_t len = strlen(path);
+
+ if (len >= sizeof(remote.sun_path)) {
+ lua_pushnil(L);
+ lua_pushstring(L, "path too long");
+ return 2;
+ }
+
+ memset(&remote, 0, sizeof(remote));
+ strcpy(remote.sun_path, path);
+ remote.sun_family = AF_UNIX;
+ timeout_markstart(tm);
+#ifdef UNIX_HAS_SUN_LEN
+ remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ + len + 1;
+ err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, remote.sun_len, tm);
+#else
+ err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote,
+ sizeof(remote.sun_family) + len, tm);
+#endif
+ if (err != IO_DONE) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixdgram_strerror(err));
+ return 2;
+ }
+ lua_pushnumber(L, (lua_Number) sent);
+ return 1;
+}
+
+static int meth_receive(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ char buf[UNIXDGRAM_DATAGRAMSIZE];
+ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
+ int err;
+ p_timeout tm = &un->tm;
+ timeout_markstart(tm);
+ if (!dgram) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "out of memory");
+ return 2;
+ }
+ err = socket_recv(&un->sock, dgram, wanted, &got, tm);
+ /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */
+ if (err != IO_DONE && err != IO_CLOSED) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixdgram_strerror(err));
+ if (wanted > sizeof(buf)) free(dgram);
+ return 2;
+ }
+ lua_pushlstring(L, dgram, got);
+ if (wanted > sizeof(buf)) free(dgram);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Receives data and sender from a DGRAM socket
+\*-------------------------------------------------------------------------*/
+static int meth_receivefrom(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
+ char buf[UNIXDGRAM_DATAGRAMSIZE];
+ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
+ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
+ struct sockaddr_un addr;
+ socklen_t addr_len = sizeof(addr);
+ int err;
+ p_timeout tm = &un->tm;
+ timeout_markstart(tm);
+ if (!dgram) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "out of memory");
+ return 2;
+ }
+ err = socket_recvfrom(&un->sock, dgram, wanted, &got, (SA *) &addr,
+ &addr_len, tm);
+ /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */
+ if (err != IO_DONE && err != IO_CLOSED) {
+ lua_pushnil(L);
+ lua_pushstring(L, unixdgram_strerror(err));
+ if (wanted > sizeof(buf)) free(dgram);
+ return 2;
+ }
+
+ lua_pushlstring(L, dgram, got);
+ /* the path may be empty, when client send without bind */
+ lua_pushstring(L, addr.sun_path);
+ if (wanted > sizeof(buf)) free(dgram);
+ return 2;
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call option handler
+\*-------------------------------------------------------------------------*/
+static int meth_setoption(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ return opt_meth_setoption(L, optset, &un->sock);
+}
+
+/*-------------------------------------------------------------------------*\
+* Select support methods
+\*-------------------------------------------------------------------------*/
+static int meth_getfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ lua_pushnumber(L, (int) un->sock);
+ return 1;
+}
+
+/* this is very dangerous, but can be handy for those that are brave enough */
+static int meth_setfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ un->sock = (t_socket) luaL_checknumber(L, 2);
+ return 0;
+}
+
+static int meth_dirty(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ (void) un;
+ lua_pushboolean(L, 0);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Binds an object to an address
+\*-------------------------------------------------------------------------*/
+static const char *unixdgram_trybind(p_unix un, const char *path) {
+ struct sockaddr_un local;
+ size_t len = strlen(path);
+ int err;
+ if (len >= sizeof(local.sun_path)) return "path too long";
+ memset(&local, 0, sizeof(local));
+ strcpy(local.sun_path, path);
+ local.sun_family = AF_UNIX;
+#ifdef UNIX_HAS_SUN_LEN
+ local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
+ + len + 1;
+ err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
+
+#else
+ err = socket_bind(&un->sock, (SA *) &local,
+ sizeof(local.sun_family) + len);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_bind(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixdgram_trybind(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+static int meth_getsockname(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ struct sockaddr_un peer = {0};
+ socklen_t peer_len = sizeof(peer);
+
+ if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(errno));
+ return 2;
+ }
+
+ lua_pushstring(L, peer.sun_path);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Turns a master unixdgram object into a client object.
+\*-------------------------------------------------------------------------*/
+static const char *unixdgram_tryconnect(p_unix un, const char *path)
+{
+ struct sockaddr_un remote;
+ int err;
+ size_t len = strlen(path);
+ if (len >= sizeof(remote.sun_path)) return "path too long";
+ memset(&remote, 0, sizeof(remote));
+ strcpy(remote.sun_path, path);
+ remote.sun_family = AF_UNIX;
+ timeout_markstart(&un->tm);
+#ifdef UNIX_HAS_SUN_LEN
+ remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ + len + 1;
+ err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
+#else
+ err = socket_connect(&un->sock, (SA *) &remote,
+ sizeof(remote.sun_family) + len, &un->tm);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_connect(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixdgram_tryconnect(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ /* turn unconnected object into a connected object */
+ auxiliar_setclass(L, "unixdgram{connected}", 1);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Closes socket used by object
+\*-------------------------------------------------------------------------*/
+static int meth_close(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ socket_destroy(&un->sock);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call tm methods
+\*-------------------------------------------------------------------------*/
+static int meth_settimeout(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ return timeout_meth_settimeout(L, &un->tm);
+}
+
+static int meth_gettimeout(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
+ return timeout_meth_gettimeout(L, &un->tm);
+}
+
+/*=========================================================================*\
+* Library functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Creates a master unixdgram object
+\*-------------------------------------------------------------------------*/
+static int global_create(lua_State *L)
+{
+ t_socket sock;
+ int err = socket_create(&sock, AF_UNIX, SOCK_DGRAM, 0);
+ /* try to allocate a system socket */
+ if (err == IO_DONE) {
+ /* allocate unixdgram object */
+ p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
+ /* set its type as master object */
+ auxiliar_setclass(L, "unixdgram{unconnected}", -1);
+ /* initialize remaining structure fields */
+ socket_setnonblocking(&sock);
+ un->sock = sock;
+ io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
+ (p_error) socket_ioerror, &un->sock);
+ timeout_init(&un->tm, -1, -1);
+ buffer_init(&un->buf, &un->io, &un->tm);
+ return 1;
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+}
diff --git a/src/unixdgram.h b/src/unixdgram.h
new file mode 100644
index 0000000..7187966
--- /dev/null
+++ b/src/unixdgram.h
@@ -0,0 +1,20 @@
+#ifndef UNIXDGRAM_H
+#define UNIXDGRAM_H
+/*=========================================================================*\
+* DGRAM object
+* LuaSocket toolkit
+*
+* The dgram.h module provides LuaSocket with support for DGRAM protocol
+* (AF_INET, SOCK_DGRAM).
+*
+* Two classes are defined: connected and unconnected. DGRAM objects are
+* originally unconnected. They can be "connected" to a given address
+* with a call to the setpeername function. The same function can be used to
+* break the connection.
+\*=========================================================================*/
+
+#include "unix.h"
+
+int unixdgram_open(lua_State *L);
+
+#endif /* UNIXDGRAM_H */
diff --git a/src/unixstream.c b/src/unixstream.c
new file mode 100644
index 0000000..0b9055c
--- /dev/null
+++ b/src/unixstream.c
@@ -0,0 +1,357 @@
+/*=========================================================================*\
+* Unix domain socket stream sub module
+* LuaSocket toolkit
+\*=========================================================================*/
+#include
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "compat.h"
+
+#include "auxiliar.h"
+#include "socket.h"
+#include "options.h"
+#include "unixstream.h"
+#include
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int global_create(lua_State *L);
+static int meth_connect(lua_State *L);
+static int meth_listen(lua_State *L);
+static int meth_bind(lua_State *L);
+static int meth_send(lua_State *L);
+static int meth_shutdown(lua_State *L);
+static int meth_receive(lua_State *L);
+static int meth_accept(lua_State *L);
+static int meth_close(lua_State *L);
+static int meth_setoption(lua_State *L);
+static int meth_settimeout(lua_State *L);
+static int meth_getfd(lua_State *L);
+static int meth_setfd(lua_State *L);
+static int meth_dirty(lua_State *L);
+static int meth_getstats(lua_State *L);
+static int meth_setstats(lua_State *L);
+static int meth_getsockname(lua_State *L);
+
+static const char *unixstream_tryconnect(p_unix un, const char *path);
+static const char *unixstream_trybind(p_unix un, const char *path);
+
+/* unixstream object methods */
+static luaL_Reg unixstream_methods[] = {
+ {"__gc", meth_close},
+ {"__tostring", auxiliar_tostring},
+ {"accept", meth_accept},
+ {"bind", meth_bind},
+ {"close", meth_close},
+ {"connect", meth_connect},
+ {"dirty", meth_dirty},
+ {"getfd", meth_getfd},
+ {"getstats", meth_getstats},
+ {"setstats", meth_setstats},
+ {"listen", meth_listen},
+ {"receive", meth_receive},
+ {"send", meth_send},
+ {"setfd", meth_setfd},
+ {"setoption", meth_setoption},
+ {"setpeername", meth_connect},
+ {"setsockname", meth_bind},
+ {"getsockname", meth_getsockname},
+ {"settimeout", meth_settimeout},
+ {"shutdown", meth_shutdown},
+ {NULL, NULL}
+};
+
+/* socket option handlers */
+static t_opt optset[] = {
+ {"keepalive", opt_set_keepalive},
+ {"reuseaddr", opt_set_reuseaddr},
+ {"linger", opt_set_linger},
+ {NULL, NULL}
+};
+
+/* functions in library namespace */
+static luaL_Reg func[] = {
+ {"stream", global_create},
+ {NULL, NULL}
+};
+
+/*-------------------------------------------------------------------------*\
+* Initializes module
+\*-------------------------------------------------------------------------*/
+int unixstream_open(lua_State *L)
+{
+ /* create classes */
+ auxiliar_newclass(L, "unixstream{master}", unixstream_methods);
+ auxiliar_newclass(L, "unixstream{client}", unixstream_methods);
+ auxiliar_newclass(L, "unixstream{server}", unixstream_methods);
+
+ /* create class groups */
+ auxiliar_add2group(L, "unixstream{master}", "unixstream{any}");
+ auxiliar_add2group(L, "unixstream{client}", "unixstream{any}");
+ auxiliar_add2group(L, "unixstream{server}", "unixstream{any}");
+
+ luaL_setfuncs(L, func, 0);
+ return 0;
+}
+
+/*=========================================================================*\
+* Lua methods
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Just call buffered IO methods
+\*-------------------------------------------------------------------------*/
+static int meth_send(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
+ return buffer_meth_send(L, &un->buf);
+}
+
+static int meth_receive(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
+ return buffer_meth_receive(L, &un->buf);
+}
+
+static int meth_getstats(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
+ return buffer_meth_getstats(L, &un->buf);
+}
+
+static int meth_setstats(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
+ return buffer_meth_setstats(L, &un->buf);
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call option handler
+\*-------------------------------------------------------------------------*/
+static int meth_setoption(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
+ return opt_meth_setoption(L, optset, &un->sock);
+}
+
+/*-------------------------------------------------------------------------*\
+* Select support methods
+\*-------------------------------------------------------------------------*/
+static int meth_getfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
+ lua_pushnumber(L, (int) un->sock);
+ return 1;
+}
+
+/* this is very dangerous, but can be handy for those that are brave enough */
+static int meth_setfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
+ un->sock = (t_socket) luaL_checknumber(L, 2);
+ return 0;
+}
+
+static int meth_dirty(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
+ lua_pushboolean(L, !buffer_isempty(&un->buf));
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Waits for and returns a client object attempting connection to the
+* server object
+\*-------------------------------------------------------------------------*/
+static int meth_accept(lua_State *L) {
+ p_unix server = (p_unix) auxiliar_checkclass(L, "unixstream{server}", 1);
+ p_timeout tm = timeout_markstart(&server->tm);
+ t_socket sock;
+ int err = socket_accept(&server->sock, &sock, NULL, NULL, tm);
+ /* if successful, push client socket */
+ if (err == IO_DONE) {
+ p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix));
+ auxiliar_setclass(L, "unixstream{client}", -1);
+ /* initialize structure fields */
+ socket_setnonblocking(&sock);
+ clnt->sock = sock;
+ io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
+ (p_error) socket_ioerror, &clnt->sock);
+ timeout_init(&clnt->tm, -1, -1);
+ buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
+ return 1;
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+}
+
+/*-------------------------------------------------------------------------*\
+* Binds an object to an address
+\*-------------------------------------------------------------------------*/
+static const char *unixstream_trybind(p_unix un, const char *path) {
+ struct sockaddr_un local;
+ size_t len = strlen(path);
+ int err;
+ if (len >= sizeof(local.sun_path)) return "path too long";
+ memset(&local, 0, sizeof(local));
+ strcpy(local.sun_path, path);
+ local.sun_family = AF_UNIX;
+#ifdef UNIX_HAS_SUN_LEN
+ local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
+ + len + 1;
+ err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
+
+#else
+ err = socket_bind(&un->sock, (SA *) &local,
+ sizeof(local.sun_family) + len);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_bind(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixstream_trybind(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+static int meth_getsockname(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
+ struct sockaddr_un peer = {0};
+ socklen_t peer_len = sizeof(peer);
+
+ if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(errno));
+ return 2;
+ }
+
+ lua_pushstring(L, peer.sun_path);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Turns a master unixstream object into a client object.
+\*-------------------------------------------------------------------------*/
+static const char *unixstream_tryconnect(p_unix un, const char *path)
+{
+ struct sockaddr_un remote;
+ int err;
+ size_t len = strlen(path);
+ if (len >= sizeof(remote.sun_path)) return "path too long";
+ memset(&remote, 0, sizeof(remote));
+ strcpy(remote.sun_path, path);
+ remote.sun_family = AF_UNIX;
+ timeout_markstart(&un->tm);
+#ifdef UNIX_HAS_SUN_LEN
+ remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ + len + 1;
+ err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
+#else
+ err = socket_connect(&un->sock, (SA *) &remote,
+ sizeof(remote.sun_family) + len, &un->tm);
+#endif
+ if (err != IO_DONE) socket_destroy(&un->sock);
+ return socket_strerror(err);
+}
+
+static int meth_connect(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
+ const char *path = luaL_checkstring(L, 2);
+ const char *err = unixstream_tryconnect(un, path);
+ if (err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ /* turn master object into a client object */
+ auxiliar_setclass(L, "unixstream{client}", 1);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Closes socket used by object
+\*-------------------------------------------------------------------------*/
+static int meth_close(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
+ socket_destroy(&un->sock);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Puts the sockt in listen mode
+\*-------------------------------------------------------------------------*/
+static int meth_listen(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
+ int backlog = (int) luaL_optnumber(L, 2, 32);
+ int err = socket_listen(&un->sock, backlog);
+ if (err != IO_DONE) {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+ /* turn master object into a server object */
+ auxiliar_setclass(L, "unixstream{server}", 1);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Shuts the connection down partially
+\*-------------------------------------------------------------------------*/
+static int meth_shutdown(lua_State *L)
+{
+ /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
+ static const char* methods[] = { "receive", "send", "both", NULL };
+ p_unix stream = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
+ int how = luaL_checkoption(L, 2, "both", methods);
+ socket_shutdown(&stream->sock, how);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Just call tm methods
+\*-------------------------------------------------------------------------*/
+static int meth_settimeout(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
+ return timeout_meth_settimeout(L, &un->tm);
+}
+
+/*=========================================================================*\
+* Library functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Creates a master unixstream object
+\*-------------------------------------------------------------------------*/
+static int global_create(lua_State *L) {
+ t_socket sock;
+ int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
+ /* try to allocate a system socket */
+ if (err == IO_DONE) {
+ /* allocate unixstream object */
+ p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
+ /* set its type as master object */
+ auxiliar_setclass(L, "unixstream{master}", -1);
+ /* initialize remaining structure fields */
+ socket_setnonblocking(&sock);
+ un->sock = sock;
+ io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
+ (p_error) socket_ioerror, &un->sock);
+ timeout_init(&un->tm, -1, -1);
+ buffer_init(&un->buf, &un->io, &un->tm);
+ return 1;
+ } else {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(err));
+ return 2;
+ }
+}
diff --git a/src/unixstream.h b/src/unixstream.h
new file mode 100644
index 0000000..ef1d071
--- /dev/null
+++ b/src/unixstream.h
@@ -0,0 +1,21 @@
+#ifndef UNIXSTREAM_H
+#define UNIXSTREAM_H
+/*=========================================================================*\
+* UNIX STREAM object
+* LuaSocket toolkit
+*
+* The unixstream.h module is basicly a glue that puts together modules buffer.h,
+* timeout.h socket.h and inet.h to provide the LuaSocket UNIX STREAM (AF_UNIX,
+* SOCK_STREAM) support.
+*
+* Three classes are defined: master, client and server. The master class is
+* a newly created unixstream object, that has not been bound or connected. Server
+* objects are unixstream objects bound to some local address. Client objects are
+* unixstream objects either connected to some address or returned by the accept
+* method of a server object.
+\*=========================================================================*/
+#include "unix.h"
+
+int unixstream_open(lua_State *L);
+
+#endif /* UNIXSTREAM_H */
diff --git a/src/unixtcp.c b/src/unixtcp.c
deleted file mode 100644
index 747ef5f..0000000
--- a/src/unixtcp.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*=========================================================================*\
-* Unix domain socket tcp sub module
-* LuaSocket toolkit
-\*=========================================================================*/
-#include
-
-#include "lua.h"
-#include "lauxlib.h"
-#include "compat.h"
-
-#include "auxiliar.h"
-#include "socket.h"
-#include "options.h"
-#include "unixtcp.h"
-#include
-
-/*=========================================================================*\
-* Internal function prototypes
-\*=========================================================================*/
-static int global_create(lua_State *L);
-static int meth_connect(lua_State *L);
-static int meth_listen(lua_State *L);
-static int meth_bind(lua_State *L);
-static int meth_send(lua_State *L);
-static int meth_shutdown(lua_State *L);
-static int meth_receive(lua_State *L);
-static int meth_accept(lua_State *L);
-static int meth_close(lua_State *L);
-static int meth_setoption(lua_State *L);
-static int meth_settimeout(lua_State *L);
-static int meth_getfd(lua_State *L);
-static int meth_setfd(lua_State *L);
-static int meth_dirty(lua_State *L);
-static int meth_getstats(lua_State *L);
-static int meth_setstats(lua_State *L);
-static int meth_getsockname(lua_State *L);
-
-static const char *unixtcp_tryconnect(p_unix un, const char *path);
-static const char *unixtcp_trybind(p_unix un, const char *path);
-
-/* unixtcp object methods */
-static luaL_Reg unixtcp_methods[] = {
- {"__gc", meth_close},
- {"__tostring", auxiliar_tostring},
- {"accept", meth_accept},
- {"bind", meth_bind},
- {"close", meth_close},
- {"connect", meth_connect},
- {"dirty", meth_dirty},
- {"getfd", meth_getfd},
- {"getstats", meth_getstats},
- {"setstats", meth_setstats},
- {"listen", meth_listen},
- {"receive", meth_receive},
- {"send", meth_send},
- {"setfd", meth_setfd},
- {"setoption", meth_setoption},
- {"setpeername", meth_connect},
- {"setsockname", meth_bind},
- {"getsockname", meth_getsockname},
- {"settimeout", meth_settimeout},
- {"shutdown", meth_shutdown},
- {NULL, NULL}
-};
-
-/* socket option handlers */
-static t_opt optset[] = {
- {"keepalive", opt_set_keepalive},
- {"reuseaddr", opt_set_reuseaddr},
- {"linger", opt_set_linger},
- {NULL, NULL}
-};
-
-/* functions in library namespace */
-static luaL_Reg func[] = {
- {"tcp", global_create},
- {NULL, NULL}
-};
-
-/*-------------------------------------------------------------------------*\
-* Initializes module
-\*-------------------------------------------------------------------------*/
-int unixtcp_open(lua_State *L)
-{
- /* create classes */
- auxiliar_newclass(L, "unixtcp{master}", unixtcp_methods);
- auxiliar_newclass(L, "unixtcp{client}", unixtcp_methods);
- auxiliar_newclass(L, "unixtcp{server}", unixtcp_methods);
-
- /* create class groups */
- auxiliar_add2group(L, "unixtcp{master}", "unixtcp{any}");
- auxiliar_add2group(L, "unixtcp{client}", "unixtcp{any}");
- auxiliar_add2group(L, "unixtcp{server}", "unixtcp{any}");
-
- luaL_setfuncs(L, func, 0);
- return 0;
-}
-
-/*=========================================================================*\
-* Lua methods
-\*=========================================================================*/
-/*-------------------------------------------------------------------------*\
-* Just call buffered IO methods
-\*-------------------------------------------------------------------------*/
-static int meth_send(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
- return buffer_meth_send(L, &un->buf);
-}
-
-static int meth_receive(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
- return buffer_meth_receive(L, &un->buf);
-}
-
-static int meth_getstats(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
- return buffer_meth_getstats(L, &un->buf);
-}
-
-static int meth_setstats(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
- return buffer_meth_setstats(L, &un->buf);
-}
-
-/*-------------------------------------------------------------------------*\
-* Just call option handler
-\*-------------------------------------------------------------------------*/
-static int meth_setoption(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
- return opt_meth_setoption(L, optset, &un->sock);
-}
-
-/*-------------------------------------------------------------------------*\
-* Select support methods
-\*-------------------------------------------------------------------------*/
-static int meth_getfd(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
- lua_pushnumber(L, (int) un->sock);
- return 1;
-}
-
-/* this is very dangerous, but can be handy for those that are brave enough */
-static int meth_setfd(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
- un->sock = (t_socket) luaL_checknumber(L, 2);
- return 0;
-}
-
-static int meth_dirty(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
- lua_pushboolean(L, !buffer_isempty(&un->buf));
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Waits for and returns a client object attempting connection to the
-* server object
-\*-------------------------------------------------------------------------*/
-static int meth_accept(lua_State *L) {
- p_unix server = (p_unix) auxiliar_checkclass(L, "unixtcp{server}", 1);
- p_timeout tm = timeout_markstart(&server->tm);
- t_socket sock;
- int err = socket_accept(&server->sock, &sock, NULL, NULL, tm);
- /* if successful, push client socket */
- if (err == IO_DONE) {
- p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix));
- auxiliar_setclass(L, "unixtcp{client}", -1);
- /* initialize structure fields */
- socket_setnonblocking(&sock);
- clnt->sock = sock;
- io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
- (p_error) socket_ioerror, &clnt->sock);
- timeout_init(&clnt->tm, -1, -1);
- buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
- return 1;
- } else {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(err));
- return 2;
- }
-}
-
-/*-------------------------------------------------------------------------*\
-* Binds an object to an address
-\*-------------------------------------------------------------------------*/
-static const char *unixtcp_trybind(p_unix un, const char *path) {
- struct sockaddr_un local;
- size_t len = strlen(path);
- int err;
- if (len >= sizeof(local.sun_path)) return "path too long";
- memset(&local, 0, sizeof(local));
- strcpy(local.sun_path, path);
- local.sun_family = AF_UNIX;
-#ifdef UNIX_HAS_SUN_LEN
- local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
- + len + 1;
- err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
-
-#else
- err = socket_bind(&un->sock, (SA *) &local,
- sizeof(local.sun_family) + len);
-#endif
- if (err != IO_DONE) socket_destroy(&un->sock);
- return socket_strerror(err);
-}
-
-static int meth_bind(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{master}", 1);
- const char *path = luaL_checkstring(L, 2);
- const char *err = unixtcp_trybind(un, path);
- if (err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- lua_pushnumber(L, 1);
- return 1;
-}
-
-static int meth_getsockname(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
- struct sockaddr_un peer = {0};
- socklen_t peer_len = sizeof(peer);
-
- if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(errno));
- return 2;
- }
-
- lua_pushstring(L, peer.sun_path);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Turns a master unixtcp object into a client object.
-\*-------------------------------------------------------------------------*/
-static const char *unixtcp_tryconnect(p_unix un, const char *path)
-{
- struct sockaddr_un remote;
- int err;
- size_t len = strlen(path);
- if (len >= sizeof(remote.sun_path)) return "path too long";
- memset(&remote, 0, sizeof(remote));
- strcpy(remote.sun_path, path);
- remote.sun_family = AF_UNIX;
- timeout_markstart(&un->tm);
-#ifdef UNIX_HAS_SUN_LEN
- remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
- + len + 1;
- err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
-#else
- err = socket_connect(&un->sock, (SA *) &remote,
- sizeof(remote.sun_family) + len, &un->tm);
-#endif
- if (err != IO_DONE) socket_destroy(&un->sock);
- return socket_strerror(err);
-}
-
-static int meth_connect(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{master}", 1);
- const char *path = luaL_checkstring(L, 2);
- const char *err = unixtcp_tryconnect(un, path);
- if (err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- /* turn master object into a client object */
- auxiliar_setclass(L, "unixtcp{client}", 1);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Closes socket used by object
-\*-------------------------------------------------------------------------*/
-static int meth_close(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
- socket_destroy(&un->sock);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Puts the sockt in listen mode
-\*-------------------------------------------------------------------------*/
-static int meth_listen(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixtcp{master}", 1);
- int backlog = (int) luaL_optnumber(L, 2, 32);
- int err = socket_listen(&un->sock, backlog);
- if (err != IO_DONE) {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(err));
- return 2;
- }
- /* turn master object into a server object */
- auxiliar_setclass(L, "unixtcp{server}", 1);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Shuts the connection down partially
-\*-------------------------------------------------------------------------*/
-static int meth_shutdown(lua_State *L)
-{
- /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
- static const char* methods[] = { "receive", "send", "both", NULL };
- p_unix tcp = (p_unix) auxiliar_checkclass(L, "unixtcp{client}", 1);
- int how = luaL_checkoption(L, 2, "both", methods);
- socket_shutdown(&tcp->sock, how);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Just call tm methods
-\*-------------------------------------------------------------------------*/
-static int meth_settimeout(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixtcp{any}", 1);
- return timeout_meth_settimeout(L, &un->tm);
-}
-
-/*=========================================================================*\
-* Library functions
-\*=========================================================================*/
-/*-------------------------------------------------------------------------*\
-* Creates a master unixtcp object
-\*-------------------------------------------------------------------------*/
-static int global_create(lua_State *L) {
- t_socket sock;
- int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
- /* try to allocate a system socket */
- if (err == IO_DONE) {
- /* allocate unixtcp object */
- p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
- /* set its type as master object */
- auxiliar_setclass(L, "unixtcp{master}", -1);
- /* initialize remaining structure fields */
- socket_setnonblocking(&sock);
- un->sock = sock;
- io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
- (p_error) socket_ioerror, &un->sock);
- timeout_init(&un->tm, -1, -1);
- buffer_init(&un->buf, &un->io, &un->tm);
- return 1;
- } else {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(err));
- return 2;
- }
-}
diff --git a/src/unixtcp.h b/src/unixtcp.h
deleted file mode 100644
index 0eababc..0000000
--- a/src/unixtcp.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef UNIXTCP_H
-#define UNIXTCP_H
-/*=========================================================================*\
-* UNIX TCP object
-* LuaSocket toolkit
-*
-* The unixtcp.h module is basicly a glue that puts together modules buffer.h,
-* timeout.h socket.h and inet.h to provide the LuaSocket UNIX TCP (AF_UNIX,
-* SOCK_STREAM) support.
-*
-* Three classes are defined: master, client and server. The master class is
-* a newly created unixtcp object, that has not been bound or connected. Server
-* objects are unixtcp objects bound to some local address. Client objects are
-* unixtcp objects either connected to some address or returned by the accept
-* method of a server object.
-\*=========================================================================*/
-#include "unix.h"
-
-int unixtcp_open(lua_State *L);
-
-#endif /* UNIXTCP_H */
diff --git a/src/unixudp.c b/src/unixudp.c
deleted file mode 100644
index 0e0a19a..0000000
--- a/src/unixudp.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*=========================================================================*\
-* Unix domain socket udp submodule
-* LuaSocket toolkit
-\*=========================================================================*/
-#include
-#include
-
-#include "lua.h"
-#include "lauxlib.h"
-#include "compat.h"
-
-#include "auxiliar.h"
-#include "socket.h"
-#include "options.h"
-#include "unix.h"
-#include
-
-#define UNIXUDP_DATAGRAMSIZE 8192
-
-/*=========================================================================*\
-* Internal function prototypes
-\*=========================================================================*/
-static int global_create(lua_State *L);
-static int meth_connect(lua_State *L);
-static int meth_bind(lua_State *L);
-static int meth_send(lua_State *L);
-static int meth_receive(lua_State *L);
-static int meth_close(lua_State *L);
-static int meth_setoption(lua_State *L);
-static int meth_settimeout(lua_State *L);
-static int meth_gettimeout(lua_State *L);
-static int meth_getfd(lua_State *L);
-static int meth_setfd(lua_State *L);
-static int meth_dirty(lua_State *L);
-static int meth_receivefrom(lua_State *L);
-static int meth_sendto(lua_State *L);
-static int meth_getsockname(lua_State *L);
-
-static const char *unixudp_tryconnect(p_unix un, const char *path);
-static const char *unixudp_trybind(p_unix un, const char *path);
-
-/* unixudp object methods */
-static luaL_Reg unixudp_methods[] = {
- {"__gc", meth_close},
- {"__tostring", auxiliar_tostring},
- {"bind", meth_bind},
- {"close", meth_close},
- {"connect", meth_connect},
- {"dirty", meth_dirty},
- {"getfd", meth_getfd},
- {"send", meth_send},
- {"sendto", meth_sendto},
- {"receive", meth_receive},
- {"receivefrom", meth_receivefrom},
- {"setfd", meth_setfd},
- {"setoption", meth_setoption},
- {"setpeername", meth_connect},
- {"setsockname", meth_bind},
- {"getsockname", meth_getsockname},
- {"settimeout", meth_settimeout},
- {"gettimeout", meth_gettimeout},
- {NULL, NULL}
-};
-
-/* socket option handlers */
-static t_opt optset[] = {
- {"reuseaddr", opt_set_reuseaddr},
- {NULL, NULL}
-};
-
-/* functions in library namespace */
-static luaL_Reg func[] = {
- {"udp", global_create},
- {NULL, NULL}
-};
-
-/*-------------------------------------------------------------------------*\
-* Initializes module
-\*-------------------------------------------------------------------------*/
-int unixudp_open(lua_State *L)
-{
- /* create classes */
- auxiliar_newclass(L, "unixudp{connected}", unixudp_methods);
- auxiliar_newclass(L, "unixudp{unconnected}", unixudp_methods);
- /* create class groups */
- auxiliar_add2group(L, "unixudp{connected}", "unixudp{any}");
- auxiliar_add2group(L, "unixudp{unconnected}", "unixudp{any}");
- auxiliar_add2group(L, "unixudp{connected}", "select{able}");
- auxiliar_add2group(L, "unixudp{unconnected}", "select{able}");
-
- luaL_setfuncs(L, func, 0);
- return 0;
-}
-
-/*=========================================================================*\
-* Lua methods
-\*=========================================================================*/
-static const char *unixudp_strerror(int err)
-{
- /* a 'closed' error on an unconnected means the target address was not
- * accepted by the transport layer */
- if (err == IO_CLOSED) return "refused";
- else return socket_strerror(err);
-}
-
-static int meth_send(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{connected}", 1);
- p_timeout tm = &un->tm;
- size_t count, sent = 0;
- int err;
- const char *data = luaL_checklstring(L, 2, &count);
- timeout_markstart(tm);
- err = socket_send(&un->sock, data, count, &sent, tm);
- if (err != IO_DONE) {
- lua_pushnil(L);
- lua_pushstring(L, unixudp_strerror(err));
- return 2;
- }
- lua_pushnumber(L, (lua_Number) sent);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Send data through unconnected unixudp socket
-\*-------------------------------------------------------------------------*/
-static int meth_sendto(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{unconnected}", 1);
- size_t count, sent = 0;
- const char *data = luaL_checklstring(L, 2, &count);
- const char *path = luaL_checkstring(L, 3);
- p_timeout tm = &un->tm;
- int err;
- struct sockaddr_un remote;
- size_t len = strlen(path);
-
- if (len >= sizeof(remote.sun_path)) {
- lua_pushnil(L);
- lua_pushstring(L, "path too long");
- return 2;
- }
-
- memset(&remote, 0, sizeof(remote));
- strcpy(remote.sun_path, path);
- remote.sun_family = AF_UNIX;
- timeout_markstart(tm);
-#ifdef UNIX_HAS_SUN_LEN
- remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
- + len + 1;
- err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, remote.sun_len, tm);
-#else
- err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote,
- sizeof(remote.sun_family) + len, tm);
-#endif
- if (err != IO_DONE) {
- lua_pushnil(L);
- lua_pushstring(L, unixudp_strerror(err));
- return 2;
- }
- lua_pushnumber(L, (lua_Number) sent);
- return 1;
-}
-
-static int meth_receive(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- char buf[UNIXUDP_DATAGRAMSIZE];
- size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
- char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
- int err;
- p_timeout tm = &un->tm;
- timeout_markstart(tm);
- if (!dgram) {
- lua_pushnil(L);
- lua_pushliteral(L, "out of memory");
- return 2;
- }
- err = socket_recv(&un->sock, dgram, wanted, &got, tm);
- /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
- if (err != IO_DONE && err != IO_CLOSED) {
- lua_pushnil(L);
- lua_pushstring(L, unixudp_strerror(err));
- if (wanted > sizeof(buf)) free(dgram);
- return 2;
- }
- lua_pushlstring(L, dgram, got);
- if (wanted > sizeof(buf)) free(dgram);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Receives data and sender from a UDP socket
-\*-------------------------------------------------------------------------*/
-static int meth_receivefrom(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{unconnected}", 1);
- char buf[UNIXUDP_DATAGRAMSIZE];
- size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
- char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
- struct sockaddr_un addr;
- socklen_t addr_len = sizeof(addr);
- int err;
- p_timeout tm = &un->tm;
- timeout_markstart(tm);
- if (!dgram) {
- lua_pushnil(L);
- lua_pushliteral(L, "out of memory");
- return 2;
- }
- err = socket_recvfrom(&un->sock, dgram, wanted, &got, (SA *) &addr,
- &addr_len, tm);
- /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
- if (err != IO_DONE && err != IO_CLOSED) {
- lua_pushnil(L);
- lua_pushstring(L, unixudp_strerror(err));
- if (wanted > sizeof(buf)) free(dgram);
- return 2;
- }
-
- lua_pushlstring(L, dgram, got);
- /* the path may be empty, when client send without bind */
- lua_pushstring(L, addr.sun_path);
- if (wanted > sizeof(buf)) free(dgram);
- return 2;
-}
-
-/*-------------------------------------------------------------------------*\
-* Just call option handler
-\*-------------------------------------------------------------------------*/
-static int meth_setoption(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- return opt_meth_setoption(L, optset, &un->sock);
-}
-
-/*-------------------------------------------------------------------------*\
-* Select support methods
-\*-------------------------------------------------------------------------*/
-static int meth_getfd(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- lua_pushnumber(L, (int) un->sock);
- return 1;
-}
-
-/* this is very dangerous, but can be handy for those that are brave enough */
-static int meth_setfd(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- un->sock = (t_socket) luaL_checknumber(L, 2);
- return 0;
-}
-
-static int meth_dirty(lua_State *L) {
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- (void) un;
- lua_pushboolean(L, 0);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Binds an object to an address
-\*-------------------------------------------------------------------------*/
-static const char *unixudp_trybind(p_unix un, const char *path) {
- struct sockaddr_un local;
- size_t len = strlen(path);
- int err;
- if (len >= sizeof(local.sun_path)) return "path too long";
- memset(&local, 0, sizeof(local));
- strcpy(local.sun_path, path);
- local.sun_family = AF_UNIX;
-#ifdef UNIX_HAS_SUN_LEN
- local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
- + len + 1;
- err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
-
-#else
- err = socket_bind(&un->sock, (SA *) &local,
- sizeof(local.sun_family) + len);
-#endif
- if (err != IO_DONE) socket_destroy(&un->sock);
- return socket_strerror(err);
-}
-
-static int meth_bind(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkclass(L, "unixudp{unconnected}", 1);
- const char *path = luaL_checkstring(L, 2);
- const char *err = unixudp_trybind(un, path);
- if (err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- lua_pushnumber(L, 1);
- return 1;
-}
-
-static int meth_getsockname(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- struct sockaddr_un peer = {0};
- socklen_t peer_len = sizeof(peer);
-
- if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(errno));
- return 2;
- }
-
- lua_pushstring(L, peer.sun_path);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Turns a master unixudp object into a client object.
-\*-------------------------------------------------------------------------*/
-static const char *unixudp_tryconnect(p_unix un, const char *path)
-{
- struct sockaddr_un remote;
- int err;
- size_t len = strlen(path);
- if (len >= sizeof(remote.sun_path)) return "path too long";
- memset(&remote, 0, sizeof(remote));
- strcpy(remote.sun_path, path);
- remote.sun_family = AF_UNIX;
- timeout_markstart(&un->tm);
-#ifdef UNIX_HAS_SUN_LEN
- remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
- + len + 1;
- err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
-#else
- err = socket_connect(&un->sock, (SA *) &remote,
- sizeof(remote.sun_family) + len, &un->tm);
-#endif
- if (err != IO_DONE) socket_destroy(&un->sock);
- return socket_strerror(err);
-}
-
-static int meth_connect(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- const char *path = luaL_checkstring(L, 2);
- const char *err = unixudp_tryconnect(un, path);
- if (err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- /* turn unconnected object into a connected object */
- auxiliar_setclass(L, "unixudp{connected}", 1);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Closes socket used by object
-\*-------------------------------------------------------------------------*/
-static int meth_close(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- socket_destroy(&un->sock);
- lua_pushnumber(L, 1);
- return 1;
-}
-
-/*-------------------------------------------------------------------------*\
-* Just call tm methods
-\*-------------------------------------------------------------------------*/
-static int meth_settimeout(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- return timeout_meth_settimeout(L, &un->tm);
-}
-
-static int meth_gettimeout(lua_State *L)
-{
- p_unix un = (p_unix) auxiliar_checkgroup(L, "unixudp{any}", 1);
- return timeout_meth_gettimeout(L, &un->tm);
-}
-
-/*=========================================================================*\
-* Library functions
-\*=========================================================================*/
-/*-------------------------------------------------------------------------*\
-* Creates a master unixudp object
-\*-------------------------------------------------------------------------*/
-static int global_create(lua_State *L)
-{
- t_socket sock;
- int err = socket_create(&sock, AF_UNIX, SOCK_DGRAM, 0);
- /* try to allocate a system socket */
- if (err == IO_DONE) {
- /* allocate unixudp object */
- p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
- /* set its type as master object */
- auxiliar_setclass(L, "unixudp{unconnected}", -1);
- /* initialize remaining structure fields */
- socket_setnonblocking(&sock);
- un->sock = sock;
- io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
- (p_error) socket_ioerror, &un->sock);
- timeout_init(&un->tm, -1, -1);
- buffer_init(&un->buf, &un->io, &un->tm);
- return 1;
- } else {
- lua_pushnil(L);
- lua_pushstring(L, socket_strerror(err));
- return 2;
- }
-}
diff --git a/src/unixudp.h b/src/unixudp.h
deleted file mode 100644
index ccfdc07..0000000
--- a/src/unixudp.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef UNIXUDP_H
-#define UNIXUDP_H
-/*=========================================================================*\
-* UDP object
-* LuaSocket toolkit
-*
-* The udp.h module provides LuaSocket with support for UDP protocol
-* (AF_INET, SOCK_DGRAM).
-*
-* Two classes are defined: connected and unconnected. UDP objects are
-* originally unconnected. They can be "connected" to a given address
-* with a call to the setpeername function. The same function can be used to
-* break the connection.
-\*=========================================================================*/
-
-#include "unix.h"
-
-int unixudp_open(lua_State *L);
-
-#endif /* UNIXUDP_H */
diff --git a/test/unixdgramclnt.lua b/test/unixdgramclnt.lua
new file mode 100644
index 0000000..9bd60f7
--- /dev/null
+++ b/test/unixdgramclnt.lua
@@ -0,0 +1,9 @@
+socket = require"socket"
+socket.unix = require"socket.unix"
+c = assert(socket.unix.dgram())
+print(c:bind("/tmp/bar"))
+while 1 do
+ local l = io.read("*l")
+ assert(c:sendto(l, "/tmp/foo"))
+ print(assert(c:receivefrom()))
+end
diff --git a/test/unixdgramsrvr.lua b/test/unixdgramsrvr.lua
new file mode 100644
index 0000000..4c11f55
--- /dev/null
+++ b/test/unixdgramsrvr.lua
@@ -0,0 +1,9 @@
+ socket = require"socket"
+ socket.unix = require"socket.unix"
+ u = assert(socket.unix.dgram())
+ assert(u:bind("/tmp/foo"))
+ while 1 do
+ x, r = assert(u:receivefrom())
+ print(x, r)
+ assert(u:sendto(">" .. x, r))
+ end
diff --git a/test/unixstreamclnt.lua b/test/unixstreamclnt.lua
new file mode 100644
index 0000000..4f2e1e3
--- /dev/null
+++ b/test/unixstreamclnt.lua
@@ -0,0 +1,8 @@
+socket = require"socket"
+socket.unix = require"socket.unix"
+c = assert(socket.unix.stream())
+assert(c:connect("/tmp/foo"))
+while 1 do
+ local l = io.read()
+ assert(c:send(l .. "\n"))
+end
diff --git a/test/unixstreamsrvr.lua b/test/unixstreamsrvr.lua
new file mode 100644
index 0000000..0a5c644
--- /dev/null
+++ b/test/unixstreamsrvr.lua
@@ -0,0 +1,9 @@
+ socket = require"socket"
+ socket.unix = require"socket.unix"
+ u = assert(socket.unix.stream())
+ assert(u:bind("/tmp/foo"))
+ assert(u:listen())
+ c = assert(u:accept())
+ while 1 do
+ print(assert(c:receive()))
+ end
diff --git a/test/unixtcpclnt.lua b/test/unixtcpclnt.lua
deleted file mode 100644
index 652a680..0000000
--- a/test/unixtcpclnt.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-socket = require"socket"
-socket.unix = require"socket.unix"
-c = assert(socket.unix.tcp())
-assert(c:connect("/tmp/foo"))
-while 1 do
- local l = io.read()
- assert(c:send(l .. "\n"))
-end
diff --git a/test/unixtcpsrvr.lua b/test/unixtcpsrvr.lua
deleted file mode 100644
index 2a2b065..0000000
--- a/test/unixtcpsrvr.lua
+++ /dev/null
@@ -1,9 +0,0 @@
- socket = require"socket"
- socket.unix = require"socket.unix"
- u = assert(socket.unix.tcp())
- assert(u:bind("/tmp/foo"))
- assert(u:listen())
- c = assert(u:accept())
- while 1 do
- print(assert(c:receive()))
- end
diff --git a/test/unixudpclnt.lua b/test/unixudpclnt.lua
deleted file mode 100644
index bbbff7f..0000000
--- a/test/unixudpclnt.lua
+++ /dev/null
@@ -1,9 +0,0 @@
-socket = require"socket"
-socket.unix = require"socket.unix"
-c = assert(socket.unix.udp())
-c:bind("/tmp/bar")
-while 1 do
- local l = io.read("*l")
- assert(c:sendto(l, "/tmp/foo"))
- print(assert(c:receivefrom()))
-end
diff --git a/test/unixudpsrvr.lua b/test/unixudpsrvr.lua
deleted file mode 100644
index 5ed71dc..0000000
--- a/test/unixudpsrvr.lua
+++ /dev/null
@@ -1,9 +0,0 @@
- socket = require"socket"
- socket.unix = require"socket.unix"
- u = assert(socket.unix.udp())
- assert(u:bind("/tmp/foo"))
- while 1 do
- x, r = assert(u:receivefrom())
- print(x, r)
- assert(u:sendto(">" .. x, r))
- end
--
cgit v1.2.3-55-g6feb
From 47e644031fed0ced1066ff843c9b42d45b54042d Mon Sep 17 00:00:00 2001
From: Diego Nehab
Date: Mon, 20 Mar 2017 16:56:15 -0300
Subject: Preserve path when parsing urls.
---
src/url.lua | 5 +++--
test/auth/.htaccess | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
(limited to 'test')
diff --git a/src/url.lua b/src/url.lua
index eb094d5..1e5a3f6 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -183,8 +183,9 @@ end
-- a stringing with the corresponding URL
-----------------------------------------------------------------------------
function _M.build(parsed)
- local ppath = _M.parse_path(parsed.path or "")
- local url = _M.build_path(ppath)
+ --local ppath = _M.parse_path(parsed.path or "")
+ --local url = _M.build_path(ppath)
+ local url = parsed.path or ""
if parsed.params then url = url .. ";" .. parsed.params end
if parsed.query then url = url .. "?" .. parsed.query end
local authority = parsed.authority
diff --git a/test/auth/.htaccess b/test/auth/.htaccess
index bb2794a..2509ae3 100644
--- a/test/auth/.htaccess
+++ b/test/auth/.htaccess
@@ -1,4 +1,4 @@
AuthName "test-auth"
AuthType Basic
- AuthUserFile /Users/diego/impa/luasocket/test/auth/.htpasswd
+ AuthUserFile /home/diego/impa/luasocket/test/auth/.htpasswd
Require valid-user
--
cgit v1.2.3-55-g6feb
From 2d6a0f7bda9241f827a3edbfa738603c024a423b Mon Sep 17 00:00:00 2001
From: Herbert Leuwer
Date: Wed, 22 Nov 2017 09:30:12 +0100
Subject: fixed url parsing; postpone fragment parsing after authority parsing;
added test cases to test/urltest.lua fixed reference patterns in
check_protect() to upper case hex letters
---
src/url.lua | 10 ++++----
test/urltest.lua | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 77 insertions(+), 8 deletions(-)
(limited to 'test')
diff --git a/src/url.lua b/src/url.lua
index 6448853..110ea94 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -139,16 +139,16 @@ function _M.parse(url, default)
parsed.authority = n
return ""
end)
- -- get query string
- url = string.gsub(url, "%?(.*)", function(q)
- parsed.query = q
- return ""
- end)
-- get fragment
url = string.gsub(url, "#(.*)$", function(f)
parsed.fragment = f
return ""
end)
+ -- get query string
+ url = string.gsub(url, "%?(.*)", function(q)
+ parsed.query = q
+ return ""
+ end)
-- get params
url = string.gsub(url, "%;(.*)", function(p)
parsed.params = p
diff --git a/test/urltest.lua b/test/urltest.lua
index 32cb348..1090a7e 100644
--- a/test/urltest.lua
+++ b/test/urltest.lua
@@ -90,6 +90,75 @@ local check_parse_url = function(gaba)
end
print("testing URL parsing")
+check_parse_url{
+ url = "scheme://user:pass$%?#wd@host:port/path;params?query#fragment",
+ scheme = "scheme",
+ authority = "user:pass$%?#wd@host:port",
+ host = "host",
+ port = "port",
+ userinfo = "user:pass$%?#wd",
+ password = "pass$%?#wd",
+ user = "user",
+ path = "/path",
+ params = "params",
+ query = "query",
+ fragment = "fragment"
+}
+check_parse_url{
+ url = "scheme://user:pass?#wd@host:port/path;params?query#fragment",
+ scheme = "scheme",
+ authority = "user:pass?#wd@host:port",
+ host = "host",
+ port = "port",
+ userinfo = "user:pass?#wd",
+ password = "pass?#wd",
+ user = "user",
+ path = "/path",
+ params = "params",
+ query = "query",
+ fragment = "fragment"
+}
+check_parse_url{
+ url = "scheme://user:pass-wd@host:port/path;params?query#fragment",
+ scheme = "scheme",
+ authority = "user:pass-wd@host:port",
+ host = "host",
+ port = "port",
+ userinfo = "user:pass-wd",
+ password = "pass-wd",
+ user = "user",
+ path = "/path",
+ params = "params",
+ query = "query",
+ fragment = "fragment"
+}
+check_parse_url{
+ url = "scheme://user:pass#wd@host:port/path;params?query#fragment",
+ scheme = "scheme",
+ authority = "user:pass#wd@host:port",
+ host = "host",
+ port = "port",
+ userinfo = "user:pass#wd",
+ password = "pass#wd",
+ user = "user",
+ path = "/path",
+ params = "params",
+ query = "query",
+ fragment = "fragment"
+}
+check_parse_url{
+ url = "scheme://user:pass#wd@host:port/path;params?query",
+ scheme = "scheme",
+ authority = "user:pass#wd@host:port",
+ host = "host",
+ port = "port",
+ userinfo = "user:pass#wd",
+ password = "pass#wd",
+ user = "user",
+ path = "/path",
+ params = "params",
+ query = "query",
+}
check_parse_url{
url = "scheme://userinfo@host:port/path;params?query#fragment",
scheme = "scheme",
@@ -608,9 +677,9 @@ check_parse_path("eu/tu", { "eu", "tu" })
print("testing path protection")
check_protect({ "eu", "-_.!~*'():@&=+$,", "tu" }, "eu/-_.!~*'():@&=+$,/tu")
check_protect({ "eu ", "~diego" }, "eu%20/~diego")
-check_protect({ "/eu>", "", "", "/
Date: Mon, 4 Jun 2018 23:23:39 -0600
Subject: Add ltn12.source.table()
---
doc/ltn12.html | 10 ++++++++++
doc/reference.html | 3 ++-
src/ltn12.lua | 10 ++++++++++
test/ltn12test.lua | 9 +++++++++
4 files changed, 31 insertions(+), 1 deletion(-)
(limited to 'test')
diff --git a/doc/ltn12.html b/doc/ltn12.html
index 54e66fb..ee2502f 100644
--- a/doc/ltn12.html
+++ b/doc/ltn12.html
@@ -405,6 +405,16 @@ Creates and returns a source that produces the contents of a
string, chunk by chunk.
+
+
+
+ltn12.source.table(table)
+
+
+
+Creates and returns a source that produces the numerically-indexed values of a table successively beginning at 1. The source returns nil (end-of-stream) whenever a nil value is produced by the current index, which proceeds forward regardless.
+
+