1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
-- original file : socket.lua
-- for more into : see util-soc.lua
local type, tostring, setmetatable = type, tostring, setmetatable
local min = math.min
local format = string.format
local socket = require("socket.core")
local connect = socket.connect
local tcp4 = socket.tcp4
local tcp6 = socket.tcp6
local getaddrinfo = socket.dns.getaddrinfo
local defaulthost = "0.0.0.0"
local function report(fmt,first,...)
if logs then
report = logs and logs.reporter("socket")
report(fmt,first,...)
elseif fmt then
fmt = "socket: " .. fmt
if first then
print(format(fmt,first,...))
else
print(fmt)
end
end
end
socket.report = report
function socket.connect4(address, port, laddress, lport)
return connect(address, port, laddress, lport, "inet")
end
function socket.connect6(address, port, laddress, lport)
return connect(address, port, laddress, lport, "inet6")
end
function socket.bind(host, port, backlog)
if host == "*" or host == "" then
host = defaulthost
end
local addrinfo, err = getaddrinfo(host)
if not addrinfo then
return nil, err
end
for i=1,#addrinfo do
local alt = addrinfo[i]
local sock, err = (alt.family == "inet" and tcp4 or tcp6)()
if not sock then
return nil, err or "unknown error"
end
sock:setoption("reuseaddr", true)
local res, err = sock:bind(alt.addr, port)
if res then
res, err = sock:listen(backlog)
if res then
return sock
else
sock:close()
end
else
sock:close()
end
end
return nil, "invalid address"
end
socket.try = socket.newtry()
function socket.choose(list)
return function(name, opt1, opt2)
if type(name) ~= "string" then
name, opt1, opt2 = "default", name, opt1
end
local f = list[name or "nil"]
if f then
return f(opt1, opt2)
else
report("error: unknown key '%s'",tostring(name))
end
end
end
local sourcet = { }
local sinkt = { }
socket.sourcet = sourcet
socket.sinkt = sinkt
socket.BLOCKSIZE = 2048
sinkt["close-when-done"] = function(sock)
return setmetatable (
{
getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end,
},
{
__call = function(self, chunk, err)
if chunk then
return sock:send(chunk)
else
sock:close()
return 1 -- why 1
end
end
}
)
end
sinkt["keep-open"] = function(sock)
return setmetatable (
{
getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end,
}, {
__call = function(self, chunk, err)
if chunk then
return sock:send(chunk)
else
return 1 -- why 1
end
end
}
)
end
sinkt["default"] = sinkt["keep-open"]
socket.sink = socket.choose(sinkt)
sourcet["by-length"] = function(sock, length)
local blocksize = socket.BLOCKSIZE
return setmetatable (
{
getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end,
},
{
__call = function()
if length <= 0 then
return nil
end
local chunk, err = sock:receive(min(blocksize,length))
if err then
return nil, err
end
length = length - #chunk
return chunk
end
}
)
end
sourcet["until-closed"] = function(sock)
local blocksize = socket.BLOCKSIZE
local done = false
return setmetatable (
{
getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end,
}, {
__call = function()
if done then
return nil
end
local chunk, status, partial = sock:receive(blocksize)
if not status then
return chunk
elseif status == "closed" then
sock:close()
done = true
return partial
else
return nil, status
end
end
}
)
end
sourcet["default"] = sourcet["until-closed"]
socket.source = socket.choose(sourcet)
_G.socket = socket -- for now global
package.loaded["socket"] = socket
return socket
|