aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Smith <osmith@sysmocom.de>2019-11-18 09:59:26 +0100
committerOliver Smith <osmith@sysmocom.de>2019-11-18 09:59:26 +0100
commit0e3aab34080cda04368244f0e3a44c2f3426e225 (patch)
treed9b4f8140115f2323925d07e7d4a65b10edd6ee9
parent5e3c9d7224758e0fd530f7718e1bb97bc5c9ae62 (diff)
contrib/freeswitch_dialplan_dgsm.py: new fileosmith/dgsm
Add example script for the distributed GSM network, which resolves the destination SIP servers of calls with osmo-mslookup-client and bridges the calls accordingly. Related: OS#4255 Change-Id: Ie4c310d2d726a72cba16503199a50b4d2177f5eb
-rwxr-xr-xcontrib/freeswitch_dialplan_dgsm.py77
1 files changed, 77 insertions, 0 deletions
diff --git a/contrib/freeswitch_dialplan_dgsm.py b/contrib/freeswitch_dialplan_dgsm.py
new file mode 100755
index 0000000..66f2d9a
--- /dev/null
+++ b/contrib/freeswitch_dialplan_dgsm.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+"""
+SPDX-License-Identifier: AGPL-3.0-or-later
+Copyright 2019 sysmocom s.f.m.c GmbH <info@sysmocom.de>
+
+This is a freeswitch dialplan implementation, see:
+https://freeswitch.org/confluence/display/FREESWITCH/mod_python
+
+Find the right SIP server with mslookup (depending on the destination number)
+and bridge calls accordingly.
+"""
+import json
+import subprocess
+
+
+def query_mslookup(service_type, id, id_type='msisdn'):
+ query_str = '%s.%s.%s' % (service_type, id, id_type)
+ print('[dialplan-dgsm] mslookup: ' + query_str)
+
+ result_line = subprocess.check_output([
+ 'osmo-mslookup-client', query_str, '-f', 'json'])
+ if isinstance(result_line, bytes):
+ result_line = result_line.decode('ascii')
+
+ print('[dialplan-dgsm] mslookup result: ' + result_line)
+ return json.loads(result_line)
+
+
+def handler(session, args):
+ """ Handle calls: bridge to the SIP server found with mslookup. """
+ print('[dialplan-dgsm] call handler')
+ msisdn = session.getVariable('destination_number')
+
+ # Run osmo-mslookup-client binary. We have also tried to directly call the
+ # C functions with ctypes but this has lead to hard-to-debug segfaults.
+ try:
+ result = query_mslookup("sip.voice", msisdn)
+
+ # This example only makes use of IPv4
+ if not result['v4']:
+ print('[dialplan-dgsm] no IPv4 result from mslookup')
+ session.hangup('UNALLOCATED_NUMBER')
+ return
+
+ sip_ip, sip_port = result['v4']
+ dial_str = 'sofia/internal/sip:{}@{}:{}'.format(
+ msisdn, sip_ip, sip_port)
+ print('[dialplan-dgsm] dial_str: ' + str(dial_str))
+
+ session.execute('bridge', dial_str)
+ except:
+ print('[dialplan-dgsm]: exception during call handler')
+ session.hangup('UNALLOCATED_NUMBER')
+
+
+def fsapi(session, stream, env, args):
+ """ Freeswitch refuses to load the module without this. """
+ stream.write(env.serialize())
+
+
+def main():
+ import argparse
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('id', type=int)
+ parser.add_argument('-i', '--id-type', default='msisdn',
+ help='default: "msisdn"')
+ parser.add_argument('-s', '--service', default='sip.voice',
+ help='default: "sip.voice"')
+ args = parser.parse_args()
+
+ result = query_mslookup(args.service, args.id, args.id_type)
+ print(json.dumps(result))
+
+
+if __name__ == '__main__':
+ main()