8e78d70f0e
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.
124 lines
4.4 KiB
Python
Executable File
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()
|