TIMESLOT TRANSLATION WORKS!

This commit is contained in:
Cort Buffington 2014-09-18 20:08:54 -05:00
parent 324c16660c
commit 648569eb91
3 changed files with 72 additions and 45 deletions

View File

@ -47,6 +47,13 @@ __email__ = 'n0mjs@me.com'
__status__ = 'beta' __status__ = 'beta'
BURST_DATA_TYPE = {
'VOICE_HEAD': '\x01',
'VOICE_TERM': '\x02',
'SLOT1_VOICE': '\x0A',
'SLOT2_VOICE': '\x8A'
}
# Notes and pieces of next steps... # 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' # RPT_WAKE_UP = b'\x85' + NETWORK[_network]['LOCAL']['RADIO_ID] + b'\x00\x00\x00\x01' + b'\x01' + b'\x01'
# TS1 = 0, TS2 = 1 # TS1 = 0, TS2 = 1
@ -70,7 +77,9 @@ for _ipsc in RULES:
for _rule in RULES[_ipsc]['GROUP_VOICE']: for _rule in RULES[_ipsc]['GROUP_VOICE']:
_rule['SRC_GROUP'] = hex_str_3(_rule['SRC_GROUP']) _rule['SRC_GROUP'] = hex_str_3(_rule['SRC_GROUP'])
_rule['DST_GROUP'] = hex_str_3(_rule['DST_GROUP']) _rule['DST_GROUP'] = hex_str_3(_rule['DST_GROUP'])
print() _rule['SRC_TS'] = _rule['SRC_TS'] - 1
_rule['DST_TS'] = _rule['DST_TS'] - 1
# Import List of Bridges # Import List of Bridges
# This is how we identify known bridges. If one of these is present # This is how we identify known bridges. If one of these is present
@ -155,6 +164,30 @@ if BRIDGES:
# Re-Write the destination Group ID # Re-Write the destination Group ID
_tmp_data = _tmp_data.replace(_dst_group, rule['DST_GROUP']) _tmp_data = _tmp_data.replace(_dst_group, rule['DST_GROUP'])
# Re-Write IPSC timeslot value
_call_info = int_id(_data[17:18])
if rule['DST_TS'] == 0:
_call_info &= ~(1 << 5)
elif rule['DST_TS'] == 1:
_call_info |= 1 << 5
_call_info = chr(_call_info)
_tmp_data = _tmp_data[:17] + _call_info + _tmp_data[18:]
# Re-Write DMR timeslot value
# Determine if the slot is present, so we can translate if need be
_burst_data_type = _data[30]
if _burst_data_type == BURST_DATA_TYPE['SLOT1_VOICE'] or _burst_data_type == BURST_DATA_TYPE['SLOT2_VOICE']:
_slot_valid = True
else:
_slot_valid = False
# Re-Write timeslot if necessary...
if _slot_valid:
if rule['DST_TS'] == 0:
_burst_data_type = BURST_DATA_TYPE['SLOT1_VOICE']
elif rule['DST_TS'] == 1:
_burst_data_type = BURST_DATA_TYPE['SLOT2_VOICE']
_tmp_data = _tmp_data[:30] + _burst_data_type + _tmp_data[31:]
# Calculate and append the authentication hash for the target network... if necessary # Calculate and append the authentication hash for the target network... if necessary
if NETWORK[_target]['LOCAL']['AUTH_ENABLED']: if NETWORK[_target]['LOCAL']['AUTH_ENABLED']:
_tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data) _tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data)
@ -184,15 +217,39 @@ else:
# timer = time() # timer = time()
for rule in RULES[_network]['GROUP_VOICE']: for rule in RULES[_network]['GROUP_VOICE']:
_target = rule['DST_NET']
# Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP) # Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP)
if rule['SRC_GROUP'] == _dst_group and rule['SRC_TS'] == _ts: if rule['SRC_GROUP'] == _dst_group and rule['SRC_TS'] == _ts:
_tmp_data = _data _tmp_data = _data
_target = rule['DST_NET']
# Re-Write the IPSC SRC to match the target network's ID # Re-Write the IPSC SRC to match the target network's ID
_tmp_data = _tmp_data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID']) _tmp_data = _tmp_data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID'])
# Re-Write the destination Group ID # Re-Write the destination Group ID
_tmp_data = _tmp_data.replace(_dst_group, rule['DST_GROUP']) _tmp_data = _tmp_data.replace(_dst_group, rule['DST_GROUP'])
# Re-Write IPSC timeslot value
_call_info = int_id(_data[17:18])
if rule['DST_TS'] == 0:
_call_info &= ~(1 << 5)
elif rule['DST_TS'] == 1:
_call_info |= 1 << 5
_call_info = chr(_call_info)
_tmp_data = _tmp_data[:17] + _call_info + _tmp_data[18:]
# Re-Write DMR timeslot value
# Determine if the slot is present, so we can translate if need be
_burst_data_type = _data[30]
if _burst_data_type == BURST_DATA_TYPE['SLOT1_VOICE'] or _burst_data_type == BURST_DATA_TYPE['SLOT2_VOICE']:
_slot_valid = True
else:
_slot_valid = False
# Re-Write timeslot if necessary...
if _slot_valid:
if rule['DST_TS'] == 0:
_burst_data_type = BURST_DATA_TYPE['SLOT1_VOICE']
elif rule['DST_TS'] == 1:
_burst_data_type = BURST_DATA_TYPE['SLOT2_VOICE']
_tmp_data = _tmp_data[:30] + _burst_data_type + _tmp_data[31:]
# Calculate and append the authentication hash for the target network... if necessary # Calculate and append the authentication hash for the target network... if necessary
if NETWORK[_target]['LOCAL']['AUTH_ENABLED']: if NETWORK[_target]['LOCAL']['AUTH_ENABLED']:
_tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data) _tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data)

View File

@ -10,14 +10,14 @@ The IPSC name must match an IPSC name from dmrlink.cfg, and any IPSC network def
as "active" in the dmrlink.cfg *MUST* have an entry here. It may be an empty entry, as "active" in the dmrlink.cfg *MUST* have an entry here. It may be an empty entry,
but there must be one so that the data structure can be parsed. but there must be one so that the data structure can be parsed.
The example below cross-patches TGID 1 on an IPSC network named "IPSC_FOO" with TGID 2 The example below cross-patches TS 1/TGID 1 on an IPSC network named "IPSC_FOO" with
on an IPSC network named "IPSC_BAR". Note, one entry must be made on EACH IPSC network TS 2/TGID 2 on an IPSC network named "IPSC_BAR". Note, one entry must be made on EACH
(IPSC_FOO and IPSC_BAR in this example) for bridging to occur in both directions. IPSC network (IPSC_FOO and IPSC_BAR in this example) for bridging to occur in both
directions.
THIS EXAMPLE WILL NOT WORK AS IT IS - YOU MUST SPECIFY NAMES AND GROUP IDS!!! THIS EXAMPLE WILL NOT WORK AS IT IS - YOU MUST SPECIFY NAMES AND GROUP IDS!!!
NOTES: NOTES:
* Timeslot transcoding does not yet work (SRC_TS) and (DST_TS) are ignored.
* Only GROUP_VOICE is currently used by the bridge.py appication, the other * Only GROUP_VOICE is currently used by the bridge.py appication, the other
types are placeholders for when it does more. types are placeholders for when it does more.
''' '''
@ -25,7 +25,7 @@ NOTES:
RULES = { RULES = {
'IPSC_FOO': { 'IPSC_FOO': {
'GROUP_VOICE': [ 'GROUP_VOICE': [
{'SRC_GROUP': 1, 'SRC_TS': 1, 'DST_NET': 'IPSC_BAR', 'DST_GROUP': 2, 'DST_TS': 1}, {'SRC_GROUP': 1, 'SRC_TS': 1, 'DST_NET': 'IPSC_BAR', 'DST_GROUP': 2, 'DST_TS': 2},
# Repeat the above line for as many rules for this IPSC network as you want. # Repeat the above line for as many rules for this IPSC network as you want.
], ],
'PRIVATE_VOICE': [ 'PRIVATE_VOICE': [
@ -37,7 +37,7 @@ RULES = {
}, },
'IPSC_BAR': { 'IPSC_BAR': {
'GROUP_VOICE': [ 'GROUP_VOICE': [
{'SRC_GROUP': 2, 'SRC_TS': 1, 'DST_NET': 'IPSC_FOO', 'DST_GROUP': 1, 'DST_TS': 1}, {'SRC_GROUP': 2, 'SRC_TS': 2, 'DST_NET': 'IPSC_FOO', 'DST_GROUP': 1, 'DST_TS': 1},
# Repeat the above line for as many rules for this IPSC network as you want. # Repeat the above line for as many rules for this IPSC network as you want.
], ],
'PRIVATE_VOICE': [ 'PRIVATE_VOICE': [

View File

@ -111,41 +111,11 @@ REPEAT = {
} }
# Conditions for accepting certain types of messages... the cornerstone of a secure IPSC system :) # DMR IPSC Contants (in the RTP Payload)
'''
REQ_VALID_PEER = [
PEER_REG_REQ,
PEER_REG_REPLY
]
REQ_VALID_MASTER = [ BURST_DATA_TYPE = {
MASTER_REG_REQ, 'VOICE_HEAD': '\x01',
MASTER_REG_REPLY 'VOICE_TERM': '\x02',
] 'SLOT1_VOICE': '\x0A',
'SLOT2_VOICE': '\x8A'
REQ_MASTER_CONNECTED = [ }
CALL_MON_STATUS,
CALL_MON_RPT,
CALL_MON_NACK,
XCMP_XNL,
GROUP_VOICE,
PVT_VOICE,
GROUP_DATA,
GROUP_VOICE,
PVT_DATA,
RPT_WAKE_UP,
MASTER_ALIVE_REQ,
MASTER_ALIVE_REPLY,
DE_REG_REQ,
DE_REG_REPLY
]
REQ_PEER_CONNECTED = [
PEER_ALIVE_REQ,
PEER_ALIVE_REPLY
]
REQ_VALID_MASTER_OR_PEER = [
REQ_VALID_PEER, REQ_VALID_MASTER
]
'''