[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