]> git.ipfire.org Git - ipfire.org.git/blame - src/backend/asterisk.py
Introduce autotools
[ipfire.org.git] / src / backend / asterisk.py
CommitLineData
5ac74b02
MT
1#!/usr/bin/python
2
3import logging
4import socket
5import time
6
7log = logging.getLogger("asterisk")
8
9class AsteriskManager(object):
10 def __init__(self, address, port=5038, username=None, password=None, timeout=10):
11 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
12 self.socket.settimeout(timeout)
13 self.socket.connect((address, port))
14
15 self.conn = self.socket.makefile("rw", 0)
16
17 self._authenticate(username, password)
18
19 def _authenticate(self, username, password):
20 banner = self.conn.readline()
21
22 if not banner.startswith("Asterisk Call Manager"):
23 raise RuntimeError("Did not connect to an Asterisk here")
24
25 self._send_action("Login", {
26 "Username" : username,
27 "Secret" : password,
28 "Events" : "off",
29 })
30
31 def _make_action_id(self):
32 return "%s" % time.time()
33
34 def _send_action(self, action, parameters={}):
35 self._send("Action", action)
36
37 action_id = self._make_action_id()
38 self._send("ActionID", action_id)
39
40 for k, v in parameters.items():
41 self._send(k, v)
42
43 return self._submit()
44
45 def _send(self, key, value):
46 line = "%s: %s" % (key, value)
47 log.debug("S: %s" % line)
48
49 self.conn.write("%s\r\n" % line)
50
51 def _recv(self):
52 line = self.conn.readline()
53 line = line.rstrip()
54
55 log.debug("R: %s" % line)
56
57 return line
58
59 def _recv_response(self):
60 response = {}
61
62 while True:
63 # Read one line
64 line = self._recv()
65
66 # An empty line signals end of response
67 if not line:
68 break
69
70 k, sep, v = line.partition(": ")
71 response[k] = v
72
73 return response
74
75 def _submit(self):
76 # End command
77 self.conn.write("\r\n")
78
79 # Read response
80 res = self._recv_response()
81
82 if res["Response"] == "Error":
83 raise Exception(res["Message"])
84
85 if res.get("EventList") == "start":
86 events = []
87
88 while True:
89 event = self._recv_response()
90
91 # This is the end of the list
92 if event.get("EventList") == "Complete":
93 break
94
95 events.append(event)
96
97 # Return event list
98 return events
99
100 return res
101
102 def ping(self):
103 """
104 Sends a ping to asterisk and expects pong
105 """
106 res = self._send_action("Ping")
107
108 return res["Ping"] == "Pong"
109
731637a8 110 def call(self, caller, callee, caller_id=None, timeout=30000):
5ac74b02 111 res = self._send_action("Originate", {
909b9713 112 "Channel" : "SIP/%s@kamailio" % caller,
5ac74b02
MT
113 "Exten" : callee,
114 "Context" : "from-cli",
115 "Priority" : 1,
116 "Timeout" : timeout,
731637a8 117 "CallerID" : caller_id or caller,
5ac74b02
MT
118 })
119
120 return res
121
122 def list_channels(self):
123 channels = []
124
125 for c in self._send_action("CoreShowChannels"):
126 channel = Channel(self, c.get("Channel"))
127 channels.append(channel)
128
129 return sorted(channels)
130
131 def _mailbox_status(self, mailbox):
132 return self._send_action("MailboxStatus", { "Mailbox" : "%s@default" % mailbox })
133
134 def messages_waiting(self, mailbox):
135 status = self._mailbox_status(mailbox)
136
137 # Get messages waiting
138 waiting = status.get("Waiting", 0)
139
140 return int(waiting)
141
142 def list_peers(self):
143 peers = []
144
145 for p in self._send_action("SIPPeers"):
146 peer = Peer(self, p.get("ObjectName"))
147 peers.append(peer)
148
149 return sorted(peers)
150
151 def list_registry(self):
152 print self._send_action("SIPShowRegistry")
153
154
155class Channel(object):
156 def __init__(self, manager, channel_id):
157 self.manager = manager
158 self.id = channel_id
159
160 self.status = self.manager._send_action("Status", { "Channel" : self.id })[0]
161
162 def __eq__(self, other):
163 return self.id == other.id
164
165 def __lt__(self, other):
166 # Longest first
167 return not self.duration < other.duration
168
169 def __repr__(self):
170 return "<%s %s>" % (self.__class__.__name__, self.id)
171
172 def hangup(self):
173 res = self.manager._send_action("Hangup", { "Channel" : self.id })
174
175 return res["Response"] == "Success"
176
177 @property
178 def type(self):
179 return self.status.get("Type")
180
181 @property
182 def application(self):
183 return self.status.get("Application")
184
185 @property
186 def duration(self):
187 seconds = self.status.get("Seconds", None)
188
189 if seconds is None:
190 return
191
192 return int(seconds)
193
56851b01
MT
194 _states = {
195 "4" : "ringing",
196 "6" : "connected",
197 }
198
199 @property
200 def state(self):
201 state = self.status.get("ChannelState")
202
203 try:
204 return self._states[state]
205 except KeyError:
206 return
207
5ac74b02
MT
208 @property
209 def format(self):
41313ef0
MT
210 format = self.status.get("Nativeformats")
211
212 return format.lstrip("(").rstrip(")")
5ac74b02
MT
213
214 @staticmethod
215 def _format_number(number):
216 # Replace 00 by +
217 if number and number.startswith("00"):
218 return "+%s" % number[2:]
219
220 return number
221
222 @property
223 def caller(self):
224 num = self.status.get("CallerIDNum")
225
226 return self._format_number(num)
227
228 @property
229 def caller_name(self):
230 name = self.status.get("CallerIDName")
231
232 if name in ("", "<unknown>"):
233 return None
234
235 return name
236
237 @property
238 def callee(self):
56851b01
MT
239 if self.application == "ConfBridge":
240 return self.data # Will have the conference room number
241
61b16172
MT
242 elif self.application == "Echo":
243 return None
244
991a0808 245 elif self.application in ("VoiceMail", "VoiceMailMain"):
56851b01
MT
246 try:
247 user, rest = self.data.split("@", 1)
248 except:
249 return self.data
250
251 return user
252
253 num = self.status.get("EffectiveConnectedLineNum") or self.status.get("DNID")
5ac74b02
MT
254
255 return self._format_number(num)
256
56851b01
MT
257 @property
258 def application(self):
259 return self.status.get("Application")
260
261 @property
262 def data(self):
263 return self.status.get("Data")
264
5ac74b02
MT
265
266class Peer(object):
267 def __init__(self, manager, peer_id):
268 self.manager = manager
269 self.id = peer_id
270
271 self.data = self.manager._send_action("SIPShowPeer", { "Peer" : self.id })
272
273 def __repr__(self):
274 return "<%s %s>" % (self.__class__.__name__, self.id)
275
276 def __eq__(self, other):
277 return self.id == other.id
278
279 def __lt__(self, other):
280 return self.id < other.id