]> git.ipfire.org Git - ipfire.org.git/blame - src/backend/talk.py
cache static pages
[ipfire.org.git] / src / backend / talk.py
CommitLineData
66862195
MT
1#!/usr/bin/python
2
917434b8
MT
3import ipaddress
4import logging
77431b9c 5import re
9f05796c 6import time
77431b9c 7
5ac74b02 8from . import database
66862195 9
11347e46 10from .misc import Object
13e89ccc
MT
11from .decorators import *
12
13class Freeswitch(Object):
14 @lazy_property
15 def db(self):
16 credentials = {
17 "host" : self.settings.get("freeswitch_database_host"),
18 "database" : self.settings.get("freeswitch_database_name", "freeswitch"),
19 "user" : self.settings.get("freeswitch_database_user"),
20 "password" : self.settings.get("freeswitch_database_password"),
21 }
22
23 return database.Connection(**credentials)
24
917434b8
MT
25 def get_sip_registrations(self, sip_uri):
26 logging.debug("Fetching SIP registrations for %s" % sip_uri)
27
28 user, delim, domain = sip_uri.partition("@")
29
30 res = self.db.query("SELECT * FROM sip_registrations \
31 WHERE sip_user = %s AND sip_host = %s AND expires >= EXTRACT(epoch FROM CURRENT_TIMESTAMP) \
32 ORDER BY contact", user, domain)
33
34 for row in res:
35 yield SIPRegistration(self, data=row)
36
9f05796c
MT
37 def get_sip_channels(self, account):
38 res = self.db.query("SELECT * FROM channels \
39 WHERE (direction = %s AND cid_num = %s) OR \
40 (direction = %s AND callee_num = %s) ORDER BY created_epoch",
41 "inbound", account.sip_id, "outbound", account.sip_id)
42
9c50164e
MT
43 channels = []
44
9f05796c 45 for row in res:
9c50164e
MT
46 c = Channel(self, data=row)
47 channels.append(c)
48
49 return channels
9f05796c 50
917434b8
MT
51
52class SIPRegistration(object):
53 def __init__(self, freeswitch, data):
54 self.freeswitch = freeswitch
55 self.data = data
56
57 @lazy_property
58 def protocol(self):
59 m = re.match(r"Registered\(([A-Z]+)(\-NAT)?\)", self.data.status)
60
61 if m:
62 return m.group(1)
63
64 @property
65 def network_ip(self):
66 return ipaddress.ip_address(self.data.network_ip)
67
68 @property
69 def network_port(self):
70 return self.data.network_port
71
72 @property
73 def user_agent(self):
74 return self.data.user_agent
75
76 def is_reachable(self):
77 return self.data.ping_status == "Reachable"
78
79 @lazy_property
80 def latency(self):
b78ec69b 81 if self.is_reachable() and self.data.ping_time:
917434b8
MT
82 return self.data.ping_time / 1000.0
83
84
9f05796c
MT
85class Channel(object):
86 def __init__(self, freeswitch, data):
87 self.freeswitch = freeswitch
88 self.data = data
66862195 89
9f05796c
MT
90 @property
91 def backend(self):
92 return self.freeswitch.backend
13e89ccc 93
9f05796c
MT
94 @property
95 def uuid(self):
96 return self.data.uuid
66862195 97
9f05796c
MT
98 @property
99 def direction(self):
100 return self.data.direction
101
102 @lazy_property
103 def caller(self):
104 return self.backend.accounts.get_by_sip_id(self.caller_number)
105
106 @property
107 def caller_name(self):
108 return self.data.cid_name
109
110 @property
111 def caller_number(self):
112 return self.data.cid_num
113
114 @lazy_property
115 def callee(self):
116 return self.backend.accounts.get_by_sip_id(self.callee_number)
66862195 117
9f05796c
MT
118 @property
119 def callee_name(self):
120 return self.data.callee_name
121
122 @property
123 def callee_number(self):
124 return self.data.callee_num
125
126 @property
127 def called_number(self):
128 return self.data.dest
129
130 @property
131 def application(self):
132 return self.data.application
66862195 133
9f05796c
MT
134 @property
135 def application_data(self):
136 return self.data.application_data
66862195 137
9f05796c
MT
138 @property
139 def duration(self):
140 return time.time() - self.data.created_epoch
66862195 141
9f05796c
MT
142 @property
143 def codec(self):
144 # We always assume a symmetric codec
145 s = [
146 "%s @ %s kHz" % (self.data.write_codec, int(self.data.write_rate) / 1000.0),
147 ]
148
149 if self.data.write_bit_rate == "0":
150 s.append("VBR")
151 else:
152 s.append("%.0f kBit/s" % (int(self.data.write_bit_rate) / 1000.0))
66862195 153
9f05796c
MT
154 return " ".join(s)
155
fe55357f
MT
156 def is_secure(self):
157 if self.data.secure:
158 return True
159
160 return False
161
9f05796c
MT
162 @property
163 def secure(self):
fe55357f
MT
164 try:
165 transport_protocol, key_negotiation, cipher_suite = self.data.secure.split(":")
166 except:
167 return
168
169 return "%s: %s" % (key_negotiation.upper(), cipher_suite.replace("_", "-"))
9f05796c
MT
170
171
172class Talk(Object):
173 def init(self):
174 # Connect to FreeSWITCH
175 self.freeswitch = Freeswitch(self.backend)
66862195 176
401827c2
MT
177 @property
178 def accounts(self):
179 for account in self.backend.accounts:
180 if not account.is_talk_enabled():
181 continue
182
183 yield account
184
1bae74c7
MT
185 def search(self, query):
186 accounts = []
187
188 for account in self.backend.accounts.search(query):
189 if not account.is_talk_enabled():
190 continue
191
192 accounts.append(account)
193
194 return accounts
195
66862195
MT
196 # Conferences
197
198 @property
199 def conferences(self):
200 conferences = []
201
202 for no in range(1, 10):
203 conference = Conference(self.backend, no)
204 conferences.append(conference)
205
206 return conferences
207
208 def get_conference(self, id):
209 for c in self.conferences:
210 if not c.sip_id == id:
211 continue
212
213 return c
214
215
216class Conference(Object):
217 def __init__(self, backend, no):
218 Object.__init__(self, backend)
219 self.no = no
220
221 def __cmp__(self, other):
222 return cmp(self.no, other.no)
223
224 @property
225 def name(self):
226 return "IPFire Conference Room %s" % self.no
227
228 @property
229 def sip_id(self):
230 return "%s" % (9000 + self.no)
231
232 @property
233 def sip_url(self):
234 return "%s@ipfire.org" % self.sip_id
235
236 @property
237 def participants(self):
238 if not hasattr(self, "_participants"):
239 self._participants = self.backend.talk.get_ongoing_calls(sip_id=self.sip_id)
240
241 return self._participants