Oliver Smith | e53a34a | 2019-11-20 12:48:12 +0100 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | """ |
| 3 | SPDX-License-Identifier: MIT |
| 4 | Copyright 2019 sysmocom s.f.m.c GmbH <info@sysmocom.de> |
| 5 | |
| 6 | This is a freeswitch dialplan implementation, see: |
| 7 | https://freeswitch.org/confluence/display/FREESWITCH/mod_python |
| 8 | |
| 9 | Find the right SIP server with mslookup (depending on the destination number) |
| 10 | and bridge calls accordingly. |
| 11 | """ |
| 12 | import json |
| 13 | import subprocess |
| 14 | |
| 15 | |
| 16 | def query_mslookup(service_type, id, id_type='msisdn'): |
| 17 | query_str = '%s.%s.%s' % (service_type, id, id_type) |
| 18 | print('[dialplan-dgsm] mslookup: ' + query_str) |
| 19 | |
| 20 | result_line = subprocess.check_output([ |
| 21 | 'osmo-mslookup-client', query_str, '-f', 'json']) |
| 22 | if isinstance(result_line, bytes): |
| 23 | result_line = result_line.decode('ascii') |
| 24 | |
| 25 | print('[dialplan-dgsm] mslookup result: ' + result_line) |
| 26 | return json.loads(result_line) |
| 27 | |
| 28 | |
| 29 | def handler(session, args): |
| 30 | """ Handle calls: bridge to the SIP server found with mslookup. """ |
| 31 | print('[dialplan-dgsm] call handler') |
| 32 | msisdn = session.getVariable('destination_number') |
| 33 | |
| 34 | # Run osmo-mslookup-client binary. We have also tried to directly call the |
| 35 | # C functions with ctypes but this has lead to hard-to-debug segfaults. |
| 36 | try: |
| 37 | result = query_mslookup("sip.voice", msisdn) |
| 38 | |
| 39 | # This example only makes use of IPv4 |
| 40 | if not result['v4']: |
| 41 | print('[dialplan-dgsm] no IPv4 result from mslookup') |
| 42 | session.hangup('UNALLOCATED_NUMBER') |
| 43 | return |
| 44 | |
| 45 | sip_ip, sip_port = result['v4'] |
| 46 | dial_str = 'sofia/internal/sip:{}@{}:{}'.format( |
| 47 | msisdn, sip_ip, sip_port) |
| 48 | print('[dialplan-dgsm] dial_str: ' + str(dial_str)) |
| 49 | |
| 50 | session.execute('bridge', dial_str) |
| 51 | except: |
| 52 | print('[dialplan-dgsm]: exception during call handler') |
| 53 | session.hangup('UNALLOCATED_NUMBER') |
| 54 | |
| 55 | |
| 56 | def fsapi(session, stream, env, args): |
| 57 | """ Freeswitch refuses to load the module without this. """ |
| 58 | stream.write(env.serialize()) |
| 59 | |
| 60 | |
| 61 | def main(): |
| 62 | import argparse |
| 63 | |
| 64 | parser = argparse.ArgumentParser() |
| 65 | parser.add_argument('id', type=int) |
| 66 | parser.add_argument('-i', '--id-type', default='msisdn', |
| 67 | help='default: "msisdn"') |
| 68 | parser.add_argument('-s', '--service', default='sip.voice', |
| 69 | help='default: "sip.voice"') |
| 70 | args = parser.parse_args() |
| 71 | |
| 72 | result = query_mslookup(args.service, args.id, args.id_type) |
| 73 | print(json.dumps(result)) |
| 74 | |
| 75 | |
| 76 | if __name__ == '__main__': |
| 77 | main() |