1 -----------------------------------------------------------------------------
2 -- LuaSocket helper module
4 -----------------------------------------------------------------------------
6 -----------------------------------------------------------------------------
7 -- Declare module and import dependencies
8 -----------------------------------------------------------------------------
10 local string = require("string")
11 local math
= require("math")
12 local socket
= require("socket.core")
15 -----------------------------------------------------------------------------
16 -- Exported auxiliar functions
17 -----------------------------------------------------------------------------
18 function connect4(address
, port
, laddress
, lport
)
19 return socket
.connect(address
, port
, laddress
, lport
, "inet")
22 function connect6(address
, port
, laddress
, lport
)
23 return socket
.connect(address
, port
, laddress
, lport
, "inet6")
26 function bind(host
, port
, backlog
)
27 if host
== "*" then host
= "0.0.0.0" end
28 local addrinfo
, err
= socket
.dns
.getaddrinfo(host
);
29 if not addrinfo
then return nil, err
end
31 err
= "no info on address"
32 for i
, alt
in base
.ipairs(addrinfo
) do
33 if alt
.family
== "inet" then
34 sock
, err
= socket
.tcp()
36 sock
, err
= socket
.tcp6()
38 if not sock
then return nil, err
end
39 sock
:setoption("reuseaddr", true)
40 res
, err
= sock
:bind(alt
.addr
, port
)
44 res
, err
= sock
:listen(backlog
)
57 function choose(table)
58 return function(name
, opt1
, opt2
)
59 if base
.type(name
) ~= "string" then
60 name
, opt1
, opt2
= "default", name
, opt1
62 local f
= table[name
or "nil"]
63 if not f
then base
.error("unknown key (".. base
.tostring(name
) ..")", 3)
64 else return f(opt1
, opt2
) end
68 -----------------------------------------------------------------------------
69 -- Socket sources and sinks, conforming to LTN12
70 -----------------------------------------------------------------------------
71 -- create namespaces inside LuaSocket namespace
77 sinkt
["close-when-done"] = function(sock
)
78 return base
.setmetatable({
79 getfd
= function() return sock
:getfd() end,
80 dirty
= function() return sock
:dirty() end
82 __call
= function(self
, chunk
, err
)
86 else return sock
:send(chunk
) end
91 sinkt
["keep-open"] = function(sock
)
92 return base
.setmetatable({
93 getfd
= function() return sock
:getfd() end,
94 dirty
= function() return sock
:dirty() end
96 __call
= function(self
, chunk
, err
)
97 if chunk
then return sock
:send(chunk
)
103 sinkt
["default"] = sinkt
["keep-open"]
107 sourcet
["by-length"] = function(sock
, length
)
108 return base
.setmetatable({
109 getfd
= function() return sock
:getfd() end,
110 dirty
= function() return sock
:dirty() end
113 if length
<= 0 then return nil end
114 local size
= math
.min(socket
.BLOCKSIZE
, length
)
115 local chunk
, err
= sock
:receive(size
)
116 if err
then return nil, err
end
117 length
= length
- string.len(chunk
)
123 sourcet
["until-closed"] = function(sock
)
125 return base
.setmetatable({
126 getfd
= function() return sock
:getfd() end,
127 dirty
= function() return sock
:dirty() end
130 if done
then return nil end
131 local chunk
, err
, partial
= sock
:receive(socket
.BLOCKSIZE
)
132 if not err
then return chunk
133 elseif err
== "closed" then
137 else return nil, err
end
143 sourcet
["default"] = sourcet
["until-closed"]
145 source
= choose(sourcet
)