diff --git a/bridge.py b/bridge.py new file mode 100644 index 0000000..98ddf69 --- /dev/null +++ b/bridge.py @@ -0,0 +1,77 @@ +# Copyright (c) 2013 Cortney T. Buffington, N0MJS n0mjs@me.com +# +# This work is licensed under the Creative Commons Attribution-ShareAlike +# 3.0 Unported License.To view a copy of this license, visit +# http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to +# Creative Commons, 444 Castro Street, Suite 900, Mountain View, +# California, 94041, USA. + +from __future__ import print_function +from twisted.internet.protocol import DatagramProtocol +from twisted.internet import reactor +from twisted.internet import task + +import binascii +import dmrlink +from dmrlink import IPSC, UnauthIPSC, NETWORK, networks, get_info + +class bridgeIPSC(IPSC): + + def __init__(self, *args, **kwargs): + IPSC.__init__(self, *args, **kwargs) + self.ACTIVE_CALLS = [] + + def datagramReceived(self, data, (host, port)): + print(binascii.b2a_hex(data)) + + + #************************************************ + # CALLBACK FUNCTIONS FOR USER PACKET TYPES + #************************************************ + + def call_ctl_1(self, _network, _data): + pass + + def call_ctl_2(self, _network, _data): + pass + + def call_ctl_3(self, _network, _data): + pass + + def xcmp_xnl(self, _network, _data): + pass + + def group_voice(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + for source in NETWORK[_network]['RULES']['GROUP_VOICE']: + # Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP) + if source['SRC_GROUP'] == _src_group: + _target = source['DST_NET'] + _target_sock = NETWORK[_target]['MASTER']['IP'], NETWORK[_target]['MASTER']['PORT'] + # Re-Write the IPSC SRC to match the target network's ID + _data = _data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID']) + # Re-Write the destinaion Group ID + _data = _data.replace(_src_group, source['DST_GROUP']) + # Calculate and append the authentication hash for the target network... if necessary + if NETWORK[_target]['LOCAL']['AUTH_KEY'] == True: + _data = hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _data) + # Send the packet to all peers in the target IPSC + send_to_ipsc(_target, _data) + + def private_voice(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + pass + + def group_data(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + pass + + def private_data(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + pass + + +for ipsc_network in NETWORK: + if (NETWORK[ipsc_network]['LOCAL']['ENABLED']): + if NETWORK[ipsc_network]['LOCAL']['AUTH_ENABLED'] == True: + networks[ipsc_network] = bridgeIPSC(ipsc_network) + else: + networks[ipsc_network] = UnauthIPSC(ipsc_network) + reactor.listenUDP(NETWORK[ipsc_network]['LOCAL']['PORT'], networks[ipsc_network]) +reactor.run() \ No newline at end of file diff --git a/log.py b/log.py new file mode 100644 index 0000000..8cdaa1d --- /dev/null +++ b/log.py @@ -0,0 +1,94 @@ +# Copyright (c) 2013 Cortney T. Buffington, N0MJS n0mjs@me.com +# +# This work is licensed under the Creative Commons Attribution-ShareAlike +# 3.0 Unported License.To view a copy of this license, visit +# http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to +# Creative Commons, 444 Castro Street, Suite 900, Mountain View, +# California, 94041, USA. + +from __future__ import print_function +from twisted.internet.protocol import DatagramProtocol +from twisted.internet import reactor +from twisted.internet import task + +import time +import binascii +import dmrlink +from dmrlink import IPSC, UnauthIPSC, NETWORK, networks, get_info, int_id + +class logIPSC(IPSC): + def __init__(self, *args, **kwargs): + IPSC.__init__(self, *args, **kwargs) + self.ACTIVE_CALLS = [] + + #************************************************ + # CALLBACK FUNCTIONS FOR USER PACKET TYPES + #************************************************ + + def call_ctl_1(self, _network, _data): + print('({}) Call Control Type 1 Packet Received From: {}' .format(_network, _src_sub)) + + def call_ctl_2(self, _network, _data): + print('({}) Call Control Type 2 Packet Received' .format(_network)) + + def call_ctl_3(self, _network, _data): + print('({}) Call Control Type 3 Packet Received' .format(_network)) + + def xcmp_xnl(self, _network, _data): + print('({}) XCMP/XNL Packet Received From: {}' .format(_network, _src_sub)) + + def group_voice(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + # _log = logger.debug + if (_ts not in self.ACTIVE_CALLS) or _end: + _time = time.strftime('%m/%d/%y %H:%M:%S') + _dst_sub = get_info(int_id(_dst_sub)) + _peerid = get_info(int_id(_peerid)) + _src_sub = get_info(int_id(_src_sub)) + if not _end: self.ACTIVE_CALLS.append(_ts) + if _end: self.ACTIVE_CALLS.remove(_ts) + + if _ts: _ts = 2 + else: _ts = 1 + if _end: _end = 'END' + else: _end = 'START' + + print('{} ({}) Call {} Group Voice: \n\tIPSC Source:\t{}\n\tSubscriber:\t{}\n\tDestination:\t{}\n\tTimeslot\t{}' .format(_time, _network, _end, _peerid, _src_sub, _dst_sub, _ts)) + + def private_voice(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + # _log = logger.debug + if (_ts not in self.ACTIVE_CALLS) or _end: + _time = time.strftime('%m/%d/%y %H:%M:%S') + _dst_sub = get_info(int_id(_dst_sub)) + _peerid = get_info(int_id(_peerid)) + _src_sub = get_info(int_id(_src_sub)) + if not _end: self.ACTIVE_CALLS.append(_ts) + if _end: self.ACTIVE_CALLS.remove(_ts) + + if _ts: _ts = 2 + else: _ts = 1 + if _end: _end = 'END' + else: _end = 'START' + + print('{} ({}) Call {} Private Voice: \n\tIPSC Source:\t{}\n\tSubscriber:\t{}\n\tDestination:\t{}\n\tTimeslot\t{}' .format(_time, _network, _end, _peerid, _src_sub, _dst_sub, _ts)) + + def group_data(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + _dst_sub = get_info(int_id(_dst_sub)) + _peerid = get_info(int_id(_peerid)) + _src_sub = get_info(int_id(_src_sub)) + print('({}) Group Data Packet Received From: {}' .format(_network, _src_sub)) + + def private_data(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data): + _dst_sub = get_info(int_id(_dst_sub)) + _peerid = get_info(int_id(_peerid)) + _src_sub = get_info(int_id(_src_sub)) + print('({}) Private Data Packet Received From: {} To: {}' .format(_network, _src_sub, _dst_sub)) + + +for ipsc_network in NETWORK: + if (NETWORK[ipsc_network]['LOCAL']['ENABLED']): + if NETWORK[ipsc_network]['LOCAL']['AUTH_ENABLED'] == True: + networks[ipsc_network] = logIPSC(ipsc_network) + else: + networks[ipsc_network] = UnauthIPSC(ipsc_network) + reactor.listenUDP(NETWORK[ipsc_network]['LOCAL']['PORT'], networks[ipsc_network]) +reactor.run() \ No newline at end of file