1
2
3
4local setmetatable, next, type, tonumber = setmetatable, next, type, tonumber
5local find, upper = string.find, string.upper
6
7local socket = socket or require("socket")
8local ltn12 = ltn12 or require("ltn12")
9
10local skipsocket = socket.skip
11local sinksocket = socket.sink
12local tcpsocket = socket.tcp
13
14local ltn12pump = ltn12.pump
15local pumpall = ltn12pump.all
16local pumpstep = ltn12pump.step
17
18local tp = {
19 TIMEOUT = 60,
20}
21
22socket.tp = tp
23
24local function get_reply(c)
25 local line, err = c:receive()
26 local reply = line
27 if err then return
28 nil, err
29 end
30 local code, sep = skipsocket(2, find(line, "^(%d%d%d)(.?)"))
31 if not code then
32 return nil, "invalid server reply"
33 end
34 if sep == "-" then
35 local current
36 repeat
37 line, err = c:receive()
38 if err then
39 return nil, err
40 end
41 current, sep = skipsocket(2, find(line, "^(%d%d%d)(.?)"))
42 reply = reply .. "\n" .. line
43 until code == current and sep == " "
44 end
45 return code, reply
46end
47
48local methods = { }
49local mt = { __index = methods }
50
51function methods.getpeername(self)
52 return self.c:getpeername()
53end
54
55function methods.getsockname(self)
56 return self.c:getpeername()
57end
58
59function methods.check(self, ok)
60 local code, reply = get_reply(self.c)
61 if not code then
62 return nil, reply
63 end
64 local c = tonumber(code)
65 local t = type(ok)
66 if t == "function" then
67 return ok(c,reply)
68 elseif t == "table" then
69 for i=1,#ok do
70 if find(code,ok[i]) then
71 return c, reply
72 end
73 end
74 return nil, reply
75 elseif find(code, ok) then
76 return c, reply
77 else
78 return nil, reply
79 end
80end
81
82function methods.command(self, cmd, arg)
83 cmd = upper(cmd)
84 if arg then
85 cmd = cmd .. " " .. arg .. "\r\n"
86 else
87 cmd = cmd .. "\r\n"
88 end
89 return self.c:send(cmd)
90end
91
92function methods.sink(self, snk, pat)
93 local chunk, err = self.c:receive(pat)
94 return snk(chunk, err)
95end
96
97function methods.send(self, data)
98 return self.c:send(data)
99end
100
101function methods.receive(self, pat)
102 return self.c:receive(pat)
103end
104
105function methods.getfd(self)
106 return self.c:getfd()
107end
108
109function methods.dirty(self)
110 return self.c:dirty()
111end
112
113function methods.getcontrol(self)
114 return self.c
115end
116
117function methods.source(self, source, step)
118 local sink = sinksocket("keep-open", self.c)
119 local ret, err = pumpall(source, sink, step or pumpstep)
120 return ret, err
121end
122
123function methods.close(self)
124 self.c:close()
125 return 1
126end
127
128function tp.connect(host, port, timeout, create)
129 local c, e = (create or tcpsocket)()
130 if not c then
131 return nil, e
132 end
133 c:settimeout(timeout or tp.TIMEOUT)
134 local r, e = c:connect(host, port)
135 if not r then
136 c:close()
137 return nil, e
138 end
139 return setmetatable({ c = c }, mt)
140end
141
142package.loaded["socket.tp"] = tp
143
144return tp
145 |