beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luasocket / src / socket.lua
blobe8def759f47da460702f624453cec2123c412999
1 -----------------------------------------------------------------------------
2 -- LuaSocket helper module
3 -- Author: Diego Nehab
4 -----------------------------------------------------------------------------
6 -----------------------------------------------------------------------------
7 -- Declare module and import dependencies
8 -----------------------------------------------------------------------------
9 local base = _G
10 local string = require("string")
11 local math = require("math")
12 local socket = require("socket.core")
13 module("socket")
15 -----------------------------------------------------------------------------
16 -- Exported auxiliar functions
17 -----------------------------------------------------------------------------
18 function connect4(address, port, laddress, lport)
19 return socket.connect(address, port, laddress, lport, "inet")
20 end
22 function connect6(address, port, laddress, lport)
23 return socket.connect(address, port, laddress, lport, "inet6")
24 end
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
30 local sock, res
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()
35 else
36 sock, err = socket.tcp6()
37 end
38 if not sock then return nil, err end
39 sock:setoption("reuseaddr", true)
40 res, err = sock:bind(alt.addr, port)
41 if not res then
42 sock:close()
43 else
44 res, err = sock:listen(backlog)
45 if not res then
46 sock:close()
47 else
48 return sock
49 end
50 end
51 end
52 return nil, err
53 end
55 try = newtry()
57 function choose(table)
58 return function(name, opt1, opt2)
59 if base.type(name) ~= "string" then
60 name, opt1, opt2 = "default", name, opt1
61 end
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
65 end
66 end
68 -----------------------------------------------------------------------------
69 -- Socket sources and sinks, conforming to LTN12
70 -----------------------------------------------------------------------------
71 -- create namespaces inside LuaSocket namespace
72 sourcet = {}
73 sinkt = {}
75 BLOCKSIZE = 2048
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
81 }, {
82 __call = function(self, chunk, err)
83 if not chunk then
84 sock:close()
85 return 1
86 else return sock:send(chunk) end
87 end
89 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
95 }, {
96 __call = function(self, chunk, err)
97 if chunk then return sock:send(chunk)
98 else return 1 end
99 end
103 sinkt["default"] = sinkt["keep-open"]
105 sink = choose(sinkt)
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
111 }, {
112 __call = function()
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)
118 return chunk
123 sourcet["until-closed"] = function(sock)
124 local done
125 return base.setmetatable({
126 getfd = function() return sock:getfd() end,
127 dirty = function() return sock:dirty() end
128 }, {
129 __call = function()
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
134 sock:close()
135 done = 1
136 return partial
137 else return nil, err end
143 sourcet["default"] = sourcet["until-closed"]
145 source = choose(sourcet)