170 lines
3.8 KiB
Lua
170 lines
3.8 KiB
Lua
local function class(base)
|
|
local t = base and setmetatable({}, base) or {}
|
|
t.__index = t
|
|
t.__class = t
|
|
t.__base = base
|
|
|
|
function t.new(...)
|
|
local o = setmetatable({}, t)
|
|
if o.__init then
|
|
if t == ... then -- we call as Class:new()
|
|
return o:__init(select(2, ...))
|
|
else -- we call as Class.new()
|
|
return o:__init(...)
|
|
end
|
|
end
|
|
return o
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
local EventSocket = class() do
|
|
|
|
if not freeswitch then
|
|
|
|
local socket = require "socket"
|
|
local ESLParser = require "lluv.esl".ESLParser
|
|
local split_status = require "lluv.esl.utils".split_status
|
|
local Database = require "resources.functions.database"
|
|
|
|
local EOL = '\n'
|
|
|
|
local host, port, auth
|
|
|
|
function EventSocket:__init()
|
|
if not host then
|
|
local db = Database.new('system')
|
|
local settings, err = db:first_row("select event_socket_ip_address, event_socket_port, event_socket_password from v_settings")
|
|
if not settings then return nil, err end
|
|
host, port, auth = settings.event_socket_ip_address, settings.event_socket_port, settings.event_socket_password
|
|
end
|
|
|
|
return self:_connect(host, port, auth)
|
|
end
|
|
|
|
function EventSocket:_connect(host, port, password)
|
|
local err
|
|
self._cnn, err = socket.connect(host, port)
|
|
if not self._cnn then return nil, err end
|
|
|
|
self._cnn:settimeout(1)
|
|
|
|
self._parser = ESLParser.new()
|
|
local auth
|
|
while true do
|
|
local event
|
|
event, err = self:_recv_event()
|
|
if not event then break end
|
|
|
|
local ct = event:getHeader('Content-Type')
|
|
if ct == 'auth/request' then
|
|
self._cnn:send('auth ' .. password .. EOL .. EOL)
|
|
elseif ct == 'command/reply' then
|
|
local reply = event:getHeader('Reply-Text')
|
|
if reply then
|
|
local ok, status, msg = split_status(reply)
|
|
if ok then auth = true else err = msg end
|
|
else
|
|
err = 'invalid response'
|
|
end
|
|
break
|
|
end
|
|
end
|
|
|
|
if not auth then
|
|
self._cnn:close()
|
|
self._cnn = nil
|
|
return nil, err
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
function EventSocket:_recv_event()
|
|
local event, err = self._parser:next_event()
|
|
|
|
while event == true do
|
|
local str, rst
|
|
str, err, rst = self._cnn:receive("*l")
|
|
if str then self._parser:append(str):append(EOL) end
|
|
if rst then self._parser:append(rst) end
|
|
if err and err ~= 'timeout' then
|
|
break
|
|
end
|
|
event = self._parser:next_event()
|
|
end
|
|
|
|
if (not event) or (event == true) then
|
|
return nil, err
|
|
end
|
|
|
|
return event
|
|
end
|
|
|
|
function EventSocket:_request(cmd)
|
|
if not self._cnn then return nil, 'closed' end
|
|
|
|
for str in (cmd .. '\n'):gmatch("(.-)\n") do
|
|
self._cnn:send(str .. EOL)
|
|
end
|
|
self._cnn:send(EOL)
|
|
|
|
return self:_recv_event()
|
|
end
|
|
|
|
function EventSocket:api(cmd)
|
|
local event, err = self:_request('api ' .. cmd)
|
|
if not event then return nil, err end
|
|
local body = event:getBody()
|
|
if body then
|
|
local ok, status, msg = split_status(body)
|
|
if ok == nil then return body end
|
|
return ok, status, msg
|
|
end
|
|
return event:getReply()
|
|
end
|
|
|
|
function EventSocket:close()
|
|
if self._cnn then
|
|
self._cnn:close()
|
|
self._cnn = nil
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
if freeswitch then
|
|
|
|
local api
|
|
|
|
-- [+-][OK|ERR|USAGE|...][Message]
|
|
local function split_status(str)
|
|
local ok, status, msg = string.match(str, "^%s*([-+])([^%s]+)%s*(.-)%s*$")
|
|
if not ok then return nil, str end
|
|
return ok == '+', status, msg
|
|
end
|
|
|
|
function EventSocket:__init()
|
|
self._api = api or freeswitch.API()
|
|
api = self._api
|
|
return self
|
|
end
|
|
|
|
function EventSocket:api(cmd)
|
|
local result = self._api:executeString(cmd)
|
|
local ok, status, msg = split_status(result)
|
|
if ok == nil then return result end
|
|
return ok, status, msg
|
|
end
|
|
|
|
function EventSocket:close()
|
|
self._api = nil
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return EventSocket
|