[asterisk-commits] mnicholson: branch mnicholson/asttest r193826 - /team/mnicholson/asttest/astt...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon May 11 21:15:45 CDT 2009
Author: mnicholson
Date: Mon May 11 21:15:42 2009
New Revision: 193826
URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=193826
Log:
added the ability to generate a manager.conf and added functions to interact with the AMI (based on astxx and LuaSocket)
Modified:
team/mnicholson/asttest/asttest/lua/astlib.lua
Modified: team/mnicholson/asttest/asttest/lua/astlib.lua
URL: http://svn.asterisk.org/svn-view/asterisk/team/mnicholson/asttest/asttest/lua/astlib.lua?view=diff&rev=193826&r1=193825&r2=193826
==============================================================================
--- team/mnicholson/asttest/asttest/lua/astlib.lua (original)
+++ team/mnicholson/asttest/asttest/lua/astlib.lua Mon May 11 21:15:42 2009
@@ -65,6 +65,17 @@
end
return asterisk[key]
+end
+
+function asterisk:manager_connect()
+ local m = manager:new()
+
+ local res, err = m:connect("localhost", self.configs["manager.conf"]["general"].port)
+ if not res then
+ return nil, err
+ end
+
+ return m
end
function asterisk:new_config(name)
@@ -114,6 +125,20 @@
s["full"] = "notice,warning,error,debug,verbose"
end
+--- Generate manager.conf with a unique port.
+function asterisk:generate_manager_conf()
+ local c = self:new_config("manager.conf")
+ local s = c:new_section("general")
+ s["enabled"] = "yes"
+ s["bindaddr"] = "0.0.0.0"
+ s["port"] = "538" .. self.index
+
+ s = c:new_section("asttest")
+ s["secret"] = "asttest"
+ s["read"] = "all"
+ s["write"] = "all"
+end
+
function asterisk:generate_essential_configs()
for conf, func in pairs(self.essential_configs) do
if not self.configs[conf] then
@@ -245,3 +270,326 @@
f:write("\n")
end
+--
+-- Manager Interface Stuff
+--
+
+manager = {
+ action = {}
+}
+function manager:new()
+ local m = {
+ events = {},
+ responses = {},
+ event_handlers = {},
+ response_handlers = {},
+ }
+
+ setmetatable(m, self)
+ self.__index = self
+ return m
+end
+
+function manager:connect(host, port)
+ if not port then
+ port = 5038
+ end
+ local err
+ self.sock, err = socket.tcp()
+ if not self.sock then
+ return nil, err
+ end
+ local res, err = self.sock:connect(host, port)
+ if not res then
+ return nil, err
+ end
+
+ res, err = self:_parse_greeting()
+ if not res then
+ self.sock:close()
+ return nil, err
+ end
+
+ return true
+end
+
+function manager:disconnect()
+ self.sock:shutdown("both")
+ self.sock:close()
+ self.sock = nil
+end
+
+function manager:_parse_greeting()
+ local line, err = self.sock:receive("*l")
+ if not line then
+ return nil, err
+ end
+
+ self.name, self.version = line:match("(.+)/(.+)")
+ if not self.name then
+ return nil, "error parsing manager greeting: " .. line
+ end
+
+ return true
+end
+
+function manager:_read_message()
+ local line, err = self.sock:receive("*l")
+ if not line then
+ return nil, err
+ end
+
+ local header, value = line:match("(.+): (.+)")
+ if not header then
+ return nil, "error parsing message: " .. line
+ end
+
+ local m = manager.message:new()
+ m[header] = value
+ if header == "Event" then
+ table.insert(self.events, m)
+ elseif header == "Response" then
+ table.insert(self.responses, m)
+ else
+ return nil, "received unknown message type: " .. header
+ end
+
+ local follows = (value == "Follows")
+
+ while true do
+ line, err = self.sock:receive("*l")
+ if not line then
+ return nil, err
+ end
+
+ if line == "" then
+ break
+ end
+
+ header, value = line:match("(.+): (.+)")
+ if not header and not follows then
+ return nil, "error parsing message: " .. line
+ elseif not header and follows then
+ if line ~= "--END COMMAND--" then
+ m._append_data(line .. "\n")
+ end
+ else
+ m[header] = value
+ end
+ end
+ return true
+end
+
+function manager:_read_response()
+ local res, err = self:wait_response()
+ if not res then
+ return nil, err
+ end
+
+ local r = self.responses[1]
+ table.remove(self.responses, 1)
+ return r
+end
+
+function manager:_read_event()
+ local res, err = self:wait_event()
+ if not res then
+ return nil, err
+ end
+
+ local e = self.events[1]
+ table.remove(self.events, 1)
+ return e
+end
+
+function manager:pump_messages()
+ while true do
+ local read, write, err = socket.select({self.sock}, nil, 0)
+ if read[1] ~= self.sock or err == "timeout" then
+ break
+ end
+
+ local res, err = self:_read_message()
+ if not res then
+ return nil, err
+ end
+ end
+ return true
+end
+
+function manager:wait_event()
+ while #self.events == 0 do
+ local res, err = self:_read_message()
+ if not res then
+ return nil, err
+ end
+ end
+ return true
+end
+
+function manager:wait_response()
+ while #self.responses == 0 do
+ local res, err = self:_read_message()
+ if not res then
+ return nil, err
+ end
+ end
+ return true
+end
+
+function manager:process_events()
+ while #self.events ~= 0 do
+ local e = self.events[1]
+ table.remove(self.events, 1)
+
+ for event, handlers in pairs(self.event_handlers) do
+ if event == e["Event"] then
+ for i, handler in ipairs(handlers) do
+ handler(e)
+ end
+ end
+ end
+
+ -- now do the catch all handlers
+ for event, handler in pairs(self.event_handlers) do
+ if event == "" then
+ for i, handler in ipairs(handlers) do
+ handler(e)
+ end
+ end
+ end
+ end
+end
+
+function manager:process_responses()
+ while #self.response_handlers ~= 0 and #self.responses ~= 0 do
+ local f = self.response_handlers[1]
+ table.remove(self.response_handlers, 1);
+
+ f(self:_read_response());
+ end
+end
+
+function manager:register_event(event, handler)
+ local e_handler = self.event_handlers[event]
+ if not e_handler then
+ self.event_handlers[event] = {}
+ end
+
+ table.insert(self.event_handlers[event], handler)
+end
+
+function manager:unregister_event(event, handler)
+ for e, handlers in pairs(self.event_handlers) do
+ if e == event then
+ for i, h in pairs(handlers) do
+ if h == handler then
+ handlers[i] = nil
+ if #handlers == 0 then
+ self.event_handlers[e] = nil
+ end
+ return true
+ end
+ end
+ end
+ end
+ return nil
+end
+
+function manager:send_action(action, handler)
+ local response = nil
+ function handle_response(r)
+ response = r
+ end
+
+ if handler then
+ return self:send_action_async(action, handler)
+ end
+
+ local res, err = self:send_action_async(action, handle_response)
+ if not res then
+ return nil, err
+ end
+
+ while not response do
+ res, err = self:wait_response()
+ if not res then
+ return nil, err
+ end
+ self:process_responses()
+ end
+ return response
+end
+manager.__call = manager.send_action
+
+function manager:send_action_async(action, handler)
+ local res, err, i = nil, nil, 0
+ local a = action:_format()
+
+ while i < #a do
+ res, err, i = self.sock:send(a, i + 1)
+ if err then
+ return nil, err
+ else
+ i = res
+ end
+ end
+ table.insert(self.response_handlers, handler)
+ return true
+end
+
+
+--
+-- Manager Helpers
+--
+
+manager.message = {}
+function manager.message:new()
+ local m = {
+ headers = {},
+ index = {},
+ data = nil,
+ }
+ setmetatable(m, self)
+ return m
+end
+
+function manager.message:__newindex(key, value)
+ table.insert(self.headers, {key, value})
+ if not self.index[key] then
+ self.index[key] = #self.headers
+ end
+end
+
+function manager.message:__index(key)
+ if self.index[key] then
+ return self.headers[self.index[key]][2]
+ end
+
+ return manager.message[key]
+end
+
+function manager.message:_format(key)
+ local msg = ""
+ for i, header in ipairs(self.headers) do
+ msg = msg .. header[1] .. ": " .. header[2] .. "\r\n"
+ end
+ msg = msg .. "\r\n"
+ return msg
+end
+
+function manager.message:_append_data(data)
+ if not self.data then
+ self.data = data
+ else
+ self.data = self.data .. data
+ end
+end
+
+function manager.action:new(action)
+ local a = manager.message:new()
+ a["Action"] = action
+ return a
+end
+
+
More information about the asterisk-commits
mailing list