luasocket/src/tp.lua

135 lines
3.7 KiB
Lua
Raw Normal View History

-----------------------------------------------------------------------------
-- Unified SMTP/FTP subsystem
-- LuaSocket toolkit.
-- Author: Diego Nehab
-----------------------------------------------------------------------------
2004-05-30 14:36:22 -07:00
2004-06-04 08:15:45 -07:00
-----------------------------------------------------------------------------
-- Declare module and import dependencies
2004-06-04 08:15:45 -07:00
-----------------------------------------------------------------------------
2005-06-13 21:29:23 -07:00
local base = _G
2004-11-26 23:58:04 -08:00
local string = require("string")
2004-06-04 08:15:45 -07:00
local socket = require("socket")
local ltn12 = require("ltn12")
socket.tp = {}
local _M = socket.tp
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
_M.TIMEOUT = 60
-----------------------------------------------------------------------------
-- Implementation
-----------------------------------------------------------------------------
-- gets server reply (works for SMTP and FTP)
2004-06-18 14:41:44 -07:00
local function get_reply(c)
2004-05-27 23:16:43 -07:00
local code, current, sep
2004-06-18 14:41:44 -07:00
local line, err = c:receive()
local reply = line
if err then return nil, err end
2004-05-27 23:16:43 -07:00
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
if not code then return nil, "invalid server reply" end
2004-05-27 23:16:43 -07:00
if sep == "-" then -- reply is multiline
repeat
2004-06-18 14:41:44 -07:00
line, err = c:receive()
if err then return nil, err end
2004-05-27 23:16:43 -07:00
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
reply = reply .. "\n" .. line
-- reply ends with same code
until code == current and sep == " "
end
return code, reply
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)
2004-06-18 14:41:44 -07:00
local code, reply = get_reply(self.c)
if not code then return nil, reply end
2004-11-26 23:58:04 -08:00
if base.type(ok) ~= "function" then
if base.type(ok) == "table" then
2004-11-26 23:58:04 -08:00
for i, v in base.ipairs(ok) do
if string.find(code, v) then
return base.tonumber(code), reply
2004-11-26 23:58:04 -08:00
end
end
return nil, reply
else
if string.find(code, ok) then return base.tonumber(code), reply
else return nil, reply end
end
2004-11-26 23:58:04 -08:00
else return ok(base.tonumber(code), reply) end
end
function metat.__index:command(cmd, arg)
2009-05-27 02:31:38 -07:00
cmd = string.upper(cmd)
if arg then
2004-11-26 23:58:04 -08:00
return self.c:send(cmd .. " " .. arg.. "\r\n")
else
return self.c:send(cmd .. "\r\n")
2004-11-26 23:58:04 -08:00
end
end
function metat.__index:sink(snk, pat)
2016-02-11 04:56:57 -08:00
local chunk, err = self.c:receive(pat)
return snk(chunk, err)
end
function metat.__index:send(data)
2004-06-18 14:41:44 -07:00
return self.c:send(data)
end
function metat.__index:receive(pat)
2004-06-18 14:41:44 -07:00
return self.c:receive(pat)
end
function metat.__index:getfd()
2004-06-18 14:41:44 -07:00
return self.c:getfd()
end
function metat.__index:dirty()
2004-06-18 14:41:44 -07:00
return self.c:dirty()
end
function metat.__index:getcontrol()
2004-06-18 14:41:44 -07:00
return self.c
end
2004-05-25 21:58:32 -07:00
function metat.__index:source(source, step)
2004-06-18 14:41:44 -07:00
local sink = socket.sink("keep-open", self.c)
2005-08-11 22:56:32 -07:00
local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
return ret, err
end
2004-06-18 14:41:44 -07:00
-- closes the underlying c
function metat.__index:close()
2004-06-18 14:41:44 -07:00
self.c:close()
return 1
end
2004-06-18 14:41:44 -07:00
-- connect with server and return c object
function _M.connect(host, port, timeout, create)
local c, e = (create or socket.tcp)()
2004-06-18 14:41:44 -07:00
if not c then return nil, e end
c:settimeout(timeout or _M.TIMEOUT)
2004-06-18 14:41:44 -07:00
local r, e = c:connect(host, port)
if not r then
c:close()
2004-06-18 14:41:44 -07:00
return nil, e
end
2004-11-26 23:58:04 -08:00
return base.setmetatable({c = c}, metat)
2004-06-18 14:41:44 -07:00
end
2004-11-26 23:58:04 -08:00
return _M