luasocket/src/tp.lua

116 lines
3.3 KiB
Lua
Raw Normal View History

-----------------------------------------------------------------------------
-- Unified SMTP/FTP subsystem
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id$
-----------------------------------------------------------------------------
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
-----------------------------------------------------------------------------
local socket = require("socket")
local ltn12 = require("ltn12")
2004-06-04 08:15:45 -07:00
module("socket.tp")
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
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
2004-05-27 23:16:43 -07:00
until code == current and sep == " "
end
return code, reply
end
-- metatable for sock object
local metat = { __index = {} }
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
if type(ok) ~= "function" then
if type(ok) == "table" then
for i, v in ipairs(ok) do
if string.find(code, v) then return tonumber(code), reply end
end
return nil, reply
else
if string.find(code, ok) then return tonumber(code), reply
else return nil, reply end
end
else return ok(tonumber(code), reply) end
end
function metat.__index:command(cmd, arg)
2004-06-18 14:41:44 -07:00
if arg then return self.c:send(cmd .. " " .. arg.. "\r\n")
else return self.c:send(cmd .. "\r\n") end
end
function metat.__index:sink(snk, pat)
2004-06-18 14:41:44 -07:00
local chunk, err = 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)
2004-05-25 21:58:32 -07:00
return ltn12.pump.all(source, sink, step or ltn12.pump.step)
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 connect(host, port, timeout)
local c, e = socket.tcp()
if not c then return nil, e end
c:settimeout(timeout or TIMEOUT)
local r, e = c:connect(host, port)
if not r then
c:close()
return nil, e
end
return setmetatable({c = c}, metat)
end