DMRlink/bridge.py
Cort Buffington 8e78d70f0e THREE PACKET TYPES FIGURED OUT!
0x61, 0x62 and 0x63 have been mostly decoded. Still don’t know what all
of the pieces do, but know what they’re for finally!

This will mean big things for log.py as I figure out the details.
2013-11-23 17:30:12 -06:00

124 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright (c) 2013 Cortney T. Buffington, N0MJS and the K0USY Group. 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
from binascii import b2a_hex as h
from time import time
import os
import sys
import binascii
import dmrlink
from dmrlink import IPSC, UnauthIPSC, NETWORK, networks, int_id, send_to_ipsc, dmr_nat, logger
NAT = 0
#NAT = '\x2f\x9b\x80'
# Notes and pieces of next steps...
# RPT_WAKE_UP = b'\x85' + NETWORK[_network]['LOCAL']['RADIO_ID] + b'\x00\x00\x00\x01' + b'\x01' + b'\x01'
# TS1 = 0, TS2 = 1
# Import Bridging rules
#
try:
from bridge_rules import RULES
except ImportError:
sys.exit('Bridging rules file not found or invalid')
class bridgeIPSC(IPSC):
def __init__(self, *args, **kwargs):
IPSC.__init__(self, *args, **kwargs)
self.ACTIVE_CALLS = []
#************************************************
# CALLBACK FUNCTIONS FOR USER PACKET TYPES
#************************************************
def group_voice(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
if (_ts not in self.ACTIVE_CALLS):
self.ACTIVE_CALLS.append(_ts)
# send repeater wake up, but send them when a repeater is likely not TXing check time since end (see below)
if _end:
self.ACTIVE_CALLS.remove(_ts)
# flag the time here so we can test to see if the last call ened long enough ago to send a wake-up
# timer = time()
for source in RULES[_network]['GROUP_VOICE']:
# Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP)
if source['SRC_GROUP'] == _dst_sub:
_tmp_data = _data
_target = source['DST_NET']
# Re-Write the IPSC SRC to match the target network's ID
_tmp_data = _tmp_data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID'])
# Re-Write the destinaion Group ID
_tmp_data = _tmp_data.replace(_dst_sub, source['DST_GROUP'])
# Calculate and append the authentication hash for the target network... if necessary
if NAT:
_tmp_data = dmr_nat(_tmp_data, _src_sub, NAT)
if NETWORK[_target]['LOCAL']['AUTH_ENABLED'] == True:
_tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data)
# Send the packet to all peers in the target IPSC
send_to_ipsc(_target, _tmp_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
def call_mon_origin(self, _network, _data):
pass
def call_mon_rpt(self, _network, _data):
pass
def call_mon_nack(self, _network, _data):
pass
def xcmp_xnl(self, _network, _data):
pass
class bridgeUnauthIPSC(bridgeIPSC):
# There isn't a hash to build, so just return the data
#
def hashed_packet(self, _key, _data):
return _data
# Remove the hash from a packet and return the payload... except don't
#
def strip_hash(self, _data):
return _data
# Everything is validated, so just return True
#
def validate_auth(self, _key, _data):
return True
if __name__ == '__main__':
logger.info('DMRlink \'bridge.py\' (c) 2013 N0MJS & the K0USY Group - SYSTEM STARTING...')
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] = bridgeUnauthIPSC(ipsc_network)
reactor.listenUDP(NETWORK[ipsc_network]['LOCAL']['PORT'], networks[ipsc_network])
reactor.run()