320 lines
7.3 KiB
Lua
320 lines
7.3 KiB
Lua
--[[
|
|
LuCI - Lua Configuration Interface
|
|
Asterisk PBX interface library
|
|
|
|
Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
$Id$
|
|
|
|
]]--
|
|
|
|
module("luci.asterisk", package.seeall)
|
|
|
|
local _io = require("io")
|
|
local uci = require("luci.model.uci").cursor()
|
|
local sys = require("luci.sys")
|
|
local util = require("luci.util")
|
|
|
|
AST_BIN = "/usr/sbin/asterisk"
|
|
AST_FLAGS = "-r -x"
|
|
|
|
|
|
--- LuCI Asterisk io interface
|
|
-- Handles low level io.
|
|
-- @type module
|
|
io = luci.util.class()
|
|
|
|
--- Execute command and return output
|
|
-- @param command String containing the command to execute
|
|
-- @return String containing the command output
|
|
function io.exec(command)
|
|
local fh = _io.popen( "%s %s %q" %{ AST_BIN, AST_FLAGS, command }, "r" )
|
|
assert(fh, "Failed to invoke asterisk")
|
|
|
|
local buffer = fh:read("*a")
|
|
fh:close()
|
|
return buffer
|
|
end
|
|
|
|
--- Execute command and invoke given callback for each readed line
|
|
-- @param command String containing the command to execute
|
|
-- @param callback Function to call back for each line
|
|
-- @return Always true
|
|
function io.execl(command, callback)
|
|
local ln
|
|
local fh = _io.popen( "%s %s %q" %{ AST_BIN, AST_FLAGS, command }, "r" )
|
|
assert(fh, "Failed to invoke asterisk")
|
|
|
|
repeat
|
|
ln = fh:read("*l")
|
|
callback(ln)
|
|
until not ln
|
|
|
|
fh:close()
|
|
return true
|
|
end
|
|
|
|
--- Execute command and return an iterator that returns one line per invokation
|
|
-- @param command String containing the command to execute
|
|
-- @return Iterator function
|
|
function io.execi(command)
|
|
local fh = _io.popen( "%s %s %q" %{ AST_BIN, AST_FLAGS, command }, "r" )
|
|
assert(fh, "Failed to invoke asterisk")
|
|
|
|
return function()
|
|
local ln = fh:read("*l")
|
|
if not ln then fh:close() end
|
|
return ln
|
|
end
|
|
end
|
|
|
|
|
|
--- LuCI Asterisk - core status
|
|
core = luci.util.class()
|
|
|
|
--- Retrive version string.
|
|
-- @return String containing the reported asterisk version
|
|
function core.version(self)
|
|
local version = io.exec("core show version")
|
|
return version:gsub(" *\n", "")
|
|
end
|
|
|
|
|
|
--- LuCI Asterisk - SIP information.
|
|
-- @type module
|
|
sip = luci.util.class()
|
|
|
|
--- Get a list of known SIP peers
|
|
-- @return Table containing each SIP peer
|
|
function sip.peers(self)
|
|
local head = false
|
|
local peers = { }
|
|
|
|
for line in io.execi("sip show peers") do
|
|
if not head then
|
|
head = true
|
|
elseif not line:match(" sip peers ") then
|
|
local online, delay, id, uid
|
|
local name, host, dyn, nat, acl, port, status =
|
|
line:match("(.-) +(.-) +([D ]) ([N ]) (.) (%d+) +(.+)")
|
|
|
|
if host == '(Unspecified)' then host = nil end
|
|
if port == '0' then port = nil else port = tonumber(port) end
|
|
|
|
dyn = ( dyn == 'D' and true or false )
|
|
nat = ( nat == 'N' and true or false )
|
|
acl = ( acl ~= ' ' and true or false )
|
|
|
|
online, delay = status:match("(OK) %((%d+) ms%)")
|
|
|
|
if online == 'OK' then
|
|
online = true
|
|
delay = tonumber(delay)
|
|
elseif status ~= 'Unmonitored' then
|
|
online = false
|
|
delay = 0
|
|
else
|
|
online = nil
|
|
delay = 0
|
|
end
|
|
|
|
id, uid = name:match("(.+)/(.+)")
|
|
|
|
if not ( id and uid ) then
|
|
id = name .. "..."
|
|
uid = nil
|
|
end
|
|
|
|
peers[#peers+1] = {
|
|
online = online,
|
|
delay = delay,
|
|
name = id,
|
|
user = uid,
|
|
dynamic = dyn,
|
|
nat = nat,
|
|
acl = acl,
|
|
host = host,
|
|
port = port
|
|
}
|
|
end
|
|
end
|
|
|
|
return peers
|
|
end
|
|
|
|
--- Get informations of given SIP peer
|
|
-- @param peer String containing the name of the SIP peer
|
|
function sip.peer(peer)
|
|
local info = { }
|
|
local keys = { }
|
|
|
|
for line in io.execi("sip show peer " .. peer) do
|
|
if #line > 0 then
|
|
local key, val = line:match("(.-) *: +(.*)")
|
|
if key and val then
|
|
|
|
key = key:gsub("^ +",""):gsub(" +$", "")
|
|
val = val:gsub("^ +",""):gsub(" +$", "")
|
|
|
|
if key == "* Name" then
|
|
key = "Name"
|
|
elseif key == "Addr->IP" then
|
|
info.address, info.port = val:match("(.+) Port (.+)")
|
|
info.port = tonumber(info.port)
|
|
elseif key == "Status" then
|
|
info.online, info.delay = val:match("(OK) %((%d+) ms%)")
|
|
if info.online == 'OK' then
|
|
info.online = true
|
|
info.delay = tonumber(info.delay)
|
|
elseif status ~= 'Unmonitored' then
|
|
info.online = false
|
|
info.delay = 0
|
|
else
|
|
info.online = nil
|
|
info.delay = 0
|
|
end
|
|
end
|
|
|
|
if val == 'Yes' or val == 'yes' or val == '<Set>' then
|
|
val = true
|
|
elseif val == 'No' or val == 'no' then
|
|
val = false
|
|
elseif val == '<Not set>' or val == '(none)' then
|
|
val = nil
|
|
end
|
|
|
|
keys[#keys+1] = key
|
|
info[key] = val
|
|
end
|
|
end
|
|
end
|
|
|
|
return info, keys
|
|
end
|
|
|
|
|
|
--- LuCI Asterisk - Internal helpers
|
|
-- @type module
|
|
tools = luci.util.class()
|
|
|
|
--- Convert given value to a list of tokens. Split by white space.
|
|
-- @param val String or table value
|
|
-- @return Table containing tokens
|
|
function tools.parse_list(v)
|
|
local tokens = { }
|
|
|
|
v = type(v) == "table" and v or { v }
|
|
for _, v in ipairs(v) do
|
|
if type(v) == "string" then
|
|
for v in v:gmatch("(%S+)") do
|
|
tokens[#tokens+1] = v
|
|
end
|
|
end
|
|
end
|
|
|
|
return tokens
|
|
end
|
|
|
|
--- Convert given list to a collection of hyperlinks
|
|
-- @param list Table of tokens
|
|
-- @param url String pattern or callback function to construct urls (optional)
|
|
-- @param sep String containing the seperator (optional, default is ", ")
|
|
-- @return String containing the html fragment
|
|
function tools.hyperlinks(list, url, sep)
|
|
local html
|
|
|
|
local function mkurl(p, t)
|
|
if type(p) == "string" then
|
|
return p:format(t)
|
|
elseif type(p) == "function" then
|
|
return p(t)
|
|
else
|
|
return '#'
|
|
end
|
|
end
|
|
|
|
list = list or { }
|
|
url = url or "%s"
|
|
sep = sep or ", "
|
|
|
|
for _, token in ipairs(list) do
|
|
html = ( html and html .. sep or '' ) ..
|
|
'<a href="%s">%s</a>' %{ mkurl(url, token), token }
|
|
end
|
|
|
|
return html or ''
|
|
end
|
|
|
|
|
|
--- LuCI Asterisk - Dialzone
|
|
-- @type module
|
|
dialzone = luci.util.class()
|
|
|
|
--- Parse a dialzone section
|
|
-- @param zone Table containing the zone info
|
|
-- @return Table with parsed information
|
|
function dialzone.parse(z)
|
|
if z['.name'] then
|
|
return {
|
|
trunks = tools.parse_list(z.uses),
|
|
name = z['.name'],
|
|
description = z.description or z['.name'],
|
|
addprefix = z.addprefix,
|
|
matches = tools.parse_list(z.match),
|
|
intlmatches = tools.parse_list(z.international),
|
|
countrycode = z.countrycode,
|
|
localzone = z.localzone,
|
|
localprefix = z.localprefix
|
|
}
|
|
end
|
|
end
|
|
|
|
--- Get a list of known dial zones
|
|
-- @return Associative table of zones and table of zone names
|
|
function dialzone.zones()
|
|
local zones = { }
|
|
local znames = { }
|
|
uci:foreach("asterisk", "dialzone",
|
|
function(z)
|
|
zones[z['.name']] = dialzone.parse(z)
|
|
znames[#znames+1] = z['.name']
|
|
end)
|
|
return zones, znames
|
|
end
|
|
|
|
--- Get a specific dial zone
|
|
-- @param name Name of the dial zone
|
|
-- @return Table containing zone information
|
|
function dialzone.zone(n)
|
|
local zone
|
|
uci:foreach("asterisk", "dialzone",
|
|
function(z)
|
|
if z['.name'] == n then
|
|
zone = dialzone.parse(z)
|
|
end
|
|
end)
|
|
return zone
|
|
end
|
|
|
|
--- Find uci section hash for given zone number
|
|
-- @param idx Zone number
|
|
-- @return String containing the uci hash pointing to the section
|
|
function dialzone.ucisection(i)
|
|
local hash
|
|
local index = 1
|
|
i = tonumber(i)
|
|
uci:foreach("asterisk", "dialzone",
|
|
function(z)
|
|
if not hash and index == i then
|
|
hash = z['.name']
|
|
end
|
|
index = index + 1
|
|
end)
|
|
return hash
|
|
end
|