c1b099dc5a7f13918f88eb8324b3668d172709b1
[project/luci.git] / applications / luci-asterisk / luasrc / asterisk.lua
1 --[[
2 LuCI - Lua Configuration Interface
3 Asterisk PBX interface library
4
5 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 $Id$
14
15 ]]--
16
17 module("luci.asterisk", package.seeall)
18
19 local _io = require("io")
20 local sys = require("luci.sys")
21 local util = require("luci.util")
22
23 AST_BIN = "/usr/sbin/asterisk"
24 AST_FLAGS = "-r -x"
25
26
27 --- LuCI Asterisk io interface
28 -- Handles low level io.
29 -- @type module
30 io = luci.util.class()
31
32 --- Execute command and return output
33 -- @param command String containing the command to execute
34 -- @return String containing the command output
35 function io.exec(command)
36 local fh = _io.popen( "%s %s %q" %{ AST_BIN, AST_FLAGS, command }, "r" )
37 assert(fh, "Failed to invoke asterisk")
38
39 local buffer = fh:read("*a")
40 fh:close()
41 return buffer
42 end
43
44 --- Execute command and invoke given callback for each readed line
45 -- @param command String containing the command to execute
46 -- @param callback Function to call back for each line
47 -- @return Always true
48 function io.execl(command, callback)
49 local ln
50 local fh = _io.popen( "%s %s %q" %{ AST_BIN, AST_FLAGS, command }, "r" )
51 assert(fh, "Failed to invoke asterisk")
52
53 repeat
54 ln = fh:read("*l")
55 callback(ln)
56 until not ln
57
58 fh:close()
59 return true
60 end
61
62 --- Execute command and return an iterator that returns one line per invokation
63 -- @param command String containing the command to execute
64 -- @return Iterator function
65 function io.execi(command)
66 local fh = _io.popen( "%s %s %q" %{ AST_BIN, AST_FLAGS, command }, "r" )
67 assert(fh, "Failed to invoke asterisk")
68
69 return function()
70 local ln = fh:read("*l")
71 if not ln then fh:close() end
72 return ln
73 end
74 end
75
76
77 --- LuCI Asterisk - core status
78 core = luci.util.class()
79
80 --- Retrive version string.
81 -- @return String containing the reported asterisk version
82 function core.version(self)
83 local version = io.exec("core show version")
84 return version:gsub(" *\n", "")
85 end
86
87
88 --- LuCI Asterisk - SIP information.
89 -- @type module
90 sip = luci.util.class()
91
92 --- Get a list of known SIP peers
93 -- @return Table containing each SIP peer
94 function sip.peers(self)
95 local head = false
96 local peers = { }
97
98 for line in io.execi("sip show peers") do
99 if not head then
100 head = true
101 elseif not line:match(" sip peers ") then
102 local online, delay, id, uid
103 local name, host, dyn, nat, acl, port, status =
104 line:match("(.-) +(.-) +([D ]) ([N ]) (.) (%d+) +(.+)")
105
106 if host == '(Unspecified)' then host = nil end
107 if port == '0' then port = nil else port = tonumber(port) end
108
109 dyn = ( dyn == 'D' and true or false )
110 nat = ( nat == 'N' and true or false )
111 acl = ( acl ~= ' ' and true or false )
112
113 online, delay = status:match("(OK) %((%d+) ms%)")
114
115 if online == 'OK' then
116 online = true
117 delay = tonumber(delay)
118 elseif status ~= 'Unmonitored' then
119 online = false
120 delay = 0
121 else
122 online = nil
123 delay = 0
124 end
125
126 id, uid = name:match("(.+)/(.+)")
127
128 if not ( id and uid ) then
129 id = name .. "..."
130 uid = nil
131 end
132
133 peers[#peers+1] = {
134 online = online,
135 delay = delay,
136 name = id,
137 user = uid,
138 dynamic = dyn,
139 nat = nat,
140 acl = acl,
141 host = host,
142 port = port
143 }
144 end
145 end
146
147 return peers
148 end
149
150 --- Get informations of given SIP peer
151 -- @param peer String containing the name of the SIP peer
152 function sip.peer(peer)
153 local info = { }
154 local keys = { }
155
156 for line in io.execi("sip show peer " .. peer) do
157 if #line > 0 then
158 local key, val = line:match("(.-) *: +(.*)")
159 if key and val then
160
161 key = key:gsub("^ +",""):gsub(" +$", "")
162 val = val:gsub("^ +",""):gsub(" +$", "")
163
164 if key == "* Name" then
165 key = "Name"
166 elseif key == "Addr->IP" then
167 info.address, info.port = val:match("(.+) Port (.+)")
168 info.port = tonumber(info.port)
169 elseif key == "Status" then
170 info.online, info.delay = val:match("(OK) %((%d+) ms%)")
171 if info.online == 'OK' then
172 info.online = true
173 info.delay = tonumber(info.delay)
174 elseif status ~= 'Unmonitored' then
175 info.online = false
176 info.delay = 0
177 else
178 info.online = nil
179 info.delay = 0
180 end
181 end
182
183 if val == 'Yes' or val == 'yes' or val == '<Set>' then
184 val = true
185 elseif val == 'No' or val == 'no' then
186 val = false
187 elseif val == '<Not set>' or val == '(none)' then
188 val = nil
189 end
190
191 keys[#keys+1] = key
192 info[key] = val
193 end
194 end
195 end
196
197 return info, keys
198 end