Call contention handler reliable
MANY changes to make the call contention handler reliable. I’m ready to say this works pretty well.
This commit is contained in:
parent
3cfc058468
commit
e2c47ed6ca
325
bridge.py
325
bridge.py
@ -48,15 +48,15 @@ __email__ = 'n0mjs@me.com'
|
|||||||
__status__ = 'beta'
|
__status__ = 'beta'
|
||||||
|
|
||||||
|
|
||||||
|
# Constants for this application
|
||||||
|
#
|
||||||
BURST_DATA_TYPE = {
|
BURST_DATA_TYPE = {
|
||||||
'VOICE_HEAD': '\x01',
|
'VOICE_HEAD': '\x01',
|
||||||
'VOICE_TERM': '\x02',
|
'VOICE_TERM': '\x02',
|
||||||
'SLOT1_VOICE': '\x0A',
|
'SLOT1_VOICE': '\x0A',
|
||||||
'SLOT2_VOICE': '\x8A'
|
'SLOT2_VOICE': '\x8A'
|
||||||
}
|
}
|
||||||
|
TS_CLEAR_TIME = .2
|
||||||
GROUP_HANG_TIME = 5 # Set to whatever is used on this IPSC (what you use in repeaters)
|
|
||||||
TS_CLEAR_TIME = .2 # Don't mess with this one
|
|
||||||
|
|
||||||
# Import Bridging rules
|
# Import Bridging rules
|
||||||
# Note: A stanza *must* exist for any IPSC configured in the main
|
# Note: A stanza *must* exist for any IPSC configured in the main
|
||||||
@ -93,222 +93,136 @@ except ImportError:
|
|||||||
BRIDGES = []
|
BRIDGES = []
|
||||||
|
|
||||||
|
|
||||||
# The class methods we override, including __init__ will be different
|
class bridgeIPSC(IPSC):
|
||||||
# depending on whether or not there is a known_bridges.py file, and
|
def __init__(self, *args, **kwargs):
|
||||||
# hence whether or not we will implement backup/polite bridging or
|
IPSC.__init__(self, *args, **kwargs)
|
||||||
# not (standard bridging). So, we test to see if the known bridges
|
if BRIDGES:
|
||||||
# data structure "BRIDGES" was imported and had entries or not. If
|
logger.info('Initializing backup/polite bridging')
|
||||||
# it did not import or did not have any entries, standard bridging
|
|
||||||
# is used.
|
|
||||||
#
|
|
||||||
if BRIDGES:
|
|
||||||
logger.info('Initializing class methods for backup/polite bridging')
|
|
||||||
class bridgeIPSC(IPSC):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
IPSC.__init__(self, *args, **kwargs)
|
|
||||||
self.BRIDGE = False
|
self.BRIDGE = False
|
||||||
self.ACTIVE_CALLS = {'TS1':0,'TS1_TIME':0,'TS2':0,'TS2_TIME':0}
|
else:
|
||||||
logger.info('(%s) Initializing bridge status as: %s', self._network, self.BRIDGE)
|
self.BRIDGE = True
|
||||||
|
logger.info('Initializing standard bridging')
|
||||||
|
|
||||||
|
self.IPSC_STATUS = {
|
||||||
|
'TS1': {'RX_GROUP':'\x00', 'TX_GROUP':'\x00', 'RX_TIME':0, 'TX_TIME':0, 'RX_SRC_SUB':'\x00', 'TX_SRC_SUB':'\x00'},
|
||||||
|
'TS2': {'RX_GROUP':'\x00', 'TX_GROUP':'\x00', 'RX_TIME':0, 'TX_TIME':0, 'RX_SRC_SUB':'\x00', 'TX_SRC_SUB':'\x00'}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Setup the backup/polite bridging maintenance loop (based on keep-alive timer)
|
||||||
|
|
||||||
# Setup the backup/polite bridging maintenance loop (based on keep-alive timer)
|
if BRIDGES:
|
||||||
def startProtocol(self):
|
def startProtocol(self):
|
||||||
IPSC.startProtocol(self)
|
IPSC.startProtocol(self)
|
||||||
|
|
||||||
self._bridge_presence = task.LoopingCall(self.bridge_presence_loop)
|
self._bridge_presence = task.LoopingCall(self.bridge_presence_loop)
|
||||||
self._bridge_presence_loop = self._bridge_presence.start(self._local['ALIVE_TIMER'])
|
self._bridge_presence_loop = self._bridge_presence.start(self._local['ALIVE_TIMER'])
|
||||||
|
|
||||||
|
# This is the backup/polite bridge maintenance loop
|
||||||
|
def bridge_presence_loop(self):
|
||||||
|
_temp_bridge = True
|
||||||
|
for peer in BRIDGES:
|
||||||
|
_peer = hex_str_4(peer)
|
||||||
|
|
||||||
|
if _peer in self._peers.keys() and (self._peers[_peer]['MODE_DECODE']['TS_1'] or self._peers[_peer]['MODE_DECODE']['TS_2']):
|
||||||
|
_temp_bridge = False
|
||||||
|
logger.debug('(%s) Peer %s is an active bridge', self._network, int_id(_peer))
|
||||||
|
|
||||||
|
if _peer == self._master['RADIO_ID'] \
|
||||||
|
and self._master['STATUS']['CONNECTED'] \
|
||||||
|
and (self._master['MODE_DECODE']['TS_1'] or self._master['MODE_DECODE']['TS_2']):
|
||||||
|
_temp_bridge = False
|
||||||
|
logger.debug('(%s) Master %s is an active bridge',self._network, int_id(_peer))
|
||||||
|
|
||||||
|
if self.BRIDGE != _temp_bridge:
|
||||||
|
logger.info('(%s) Changing bridge status to: %s', self._network, _temp_bridge )
|
||||||
|
self.BRIDGE = _temp_bridge
|
||||||
|
|
||||||
|
|
||||||
# This is the backup/polite bridge maintenance loop
|
#************************************************
|
||||||
def bridge_presence_loop(self):
|
# CALLBACK FUNCTIONS FOR USER PACKET TYPES
|
||||||
_temp_bridge = True
|
#************************************************
|
||||||
for peer in BRIDGES:
|
#
|
||||||
_peer = hex_str_4(peer)
|
def group_voice(self, _network, _src_sub, _dst_group, _ts, _end, _peerid, _data):
|
||||||
|
logger.debug('(%s) Group Voice Packet Received From: %s, IPSC Peer %s, Destination %s', _network, int_id(_src_sub), int_id(_peerid), int_id(_dst_group))
|
||||||
if _peer in self._peers.keys() and (self._peers[_peer]['MODE_DECODE']['TS_1'] or self._peers[_peer]['MODE_DECODE']['TS_2']):
|
_burst_data_type = _data[30] # Determine the type of voice packet this is (see top of file for possible types)
|
||||||
_temp_bridge = False
|
if _ts == 0:
|
||||||
logger.debug('(%s) Peer %s is an active bridge', self._network, int_id(_peer))
|
_TS = 'TS1'
|
||||||
|
elif _ts == 1:
|
||||||
if _peer == self._master['RADIO_ID'] \
|
_TS = 'TS2'
|
||||||
and self._master['STATUS']['CONNECTED'] \
|
|
||||||
and (self._master['MODE_DECODE']['TS_1'] or self._master['MODE_DECODE']['TS_2']):
|
|
||||||
_temp_bridge = False
|
|
||||||
logger.debug('(%s) Master %s is an active bridge',self._network, int_id(_peer))
|
|
||||||
|
|
||||||
if self.BRIDGE != _temp_bridge:
|
|
||||||
logger.info('(%s) Changing bridge status to: %s', self._network, _temp_bridge )
|
|
||||||
self.BRIDGE = _temp_bridge
|
|
||||||
|
|
||||||
|
for rule in RULES[_network]['GROUP_VOICE']:
|
||||||
|
_target = rule['DST_NET'] # Shorthand to reduce length and make it easier to read
|
||||||
#************************************************
|
_status = networks[_target].IPSC_STATUS # Shorthand to reduce length and make it easier to read
|
||||||
# CALLBACK FUNCTIONS FOR USER PACKET TYPES
|
now = time() # Mark packet arrival time -- we'll need this for call contention handling
|
||||||
#************************************************
|
|
||||||
#
|
|
||||||
def group_voice(self, _network, _src_sub, _dst_group, _ts, _end, _peerid, _data):
|
|
||||||
logger.debug('(%s) Group Voice Packet Received From: %s, IPSC Peer %s, Destination %s', _network, int_id(_src_sub), int_id(_peerid), int_id(_dst_group))
|
|
||||||
_burst_data_type = _data[30] # Determine the type of voice packet this is (see top of file for possible types)
|
|
||||||
|
|
||||||
for rule in RULES[_network]['GROUP_VOICE']:
|
|
||||||
_target = rule['DST_NET'] # Shorthand to reduce length and make it easier to read
|
|
||||||
now = time() # Mark packet arrival time -- we'll need this for call contention handling
|
|
||||||
|
|
||||||
# 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 and (self.BRIDGE == True or networks[_target].BRIDGE == True):
|
|
||||||
|
|
||||||
if rule['DST_TS'] == 0:
|
# Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP)
|
||||||
if rule['DST_GROUP'] != self.ACTIVE_CALLS['TS1'] and (now - self.ACTIVE_CALLS['TS1_TIME']) < GROUP_HANG_TIME:
|
#if rule['SRC_GROUP'] == _dst_group and rule['SRC_TS'] == _ts:
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
#if BRIDGES:
|
||||||
logger.info('(%s) Call not bridged, Already bridging a call to: Destination IPSC %s, TS 1, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
if (rule['SRC_GROUP'] == _dst_group and rule['SRC_TS'] == _ts) and (self.BRIDGE == True or networks[_target].BRIDGE == True):
|
||||||
return
|
|
||||||
if ((networks[_target].ACTIVE_CALLS['TS1'] != rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS1_TIME']) < GROUP_HANG_TIME)) \
|
if ((rule['DST_GROUP'] != _status[_TS]['RX_GROUP']) and ((now - _status[_TS]['RX_TIME']) < RULES[_network]['GROUP_HANGTIME'])):
|
||||||
or ((networks[_target].ACTIVE_CALLS['TS1'] == rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS1_TIME']) < TS_CLEAR_TIME)):
|
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
logger.info('(%s) Call not bridged, target active or in group hangtime: IPSC %s, %s, TGID%s', _network, _target, _TS, int_id(rule['DST_GROUP']))
|
||||||
logger.info('(%s) Call not bridged, destination in use: Destination IPSC %s, TS 1, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
return
|
||||||
return
|
|
||||||
|
|
||||||
if rule['DST_TS'] == 1:
|
|
||||||
if rule['DST_GROUP'] != self.ACTIVE_CALLS['TS2'] and (now - self.ACTIVE_CALLS['TS2_TIME']) < GROUP_HANG_TIME:
|
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
|
||||||
logger.info('(%s) Call not bridged, Already bridging a call to: Destination IPSC %s, TS 2, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
|
||||||
return
|
|
||||||
if ((networks[_target].ACTIVE_CALLS['TS2'] != rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS2_TIME']) < GROUP_HANG_TIME)) \
|
|
||||||
or ((networks[_target].ACTIVE_CALLS['TS2'] == rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS2_TIME']) < TS_CLEAR_TIME)):
|
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
|
||||||
logger.info('(%s) Call not bridged, destination in use: Destination IPSC %s, TS 2, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
|
||||||
return
|
|
||||||
|
|
||||||
_tmp_data = _data
|
|
||||||
# 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 destination Group ID
|
|
||||||
_tmp_data = _tmp_data.replace(_dst_group, rule['DST_GROUP'])
|
|
||||||
|
|
||||||
# Re-Write IPSC timeslot value
|
if ((rule['DST_GROUP'] != _status[_TS]['TX_GROUP']) and ((now - _status[_TS]['TX_TIME']) < RULES[_network]['GROUP_HANGTIME'])):
|
||||||
_call_info = int_id(_data[17:18])
|
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
||||||
|
logger.info('(%s) Call not bridged, target in group hangtime: IPSC %s, %s, TGID%s', _network, _target, _TS, int_id(rule['DST_GROUP']))
|
||||||
|
return
|
||||||
|
|
||||||
|
if (rule['DST_GROUP'] == _status[_TS]['TX_GROUP']) and (_src_sub != _status[_TS]['TX_SRC_SUB']) and ((now - _status[_TS]['TX_TIME']) < TS_CLEAR_TIME):
|
||||||
|
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
||||||
|
logger.info('(%s) Call not bridged, call bridge in progress from %s, target: IPSC %s, %s, TGID%s', _network, int_id(_src_sub), _target, _TS, int_id(rule['DST_GROUP']))
|
||||||
|
return
|
||||||
|
|
||||||
|
if (rule['DST_GROUP'] == _status[_TS]['RX_GROUP']) and ((now - _status[_TS]['RX_TIME']) < TS_CLEAR_TIME):
|
||||||
|
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
||||||
|
logger.info('(%s) Call not bridged, matching call already active on target: IPSC %s, %s, TGID%s', _network, _target, _TS, int_id(rule['DST_GROUP']))
|
||||||
|
return
|
||||||
|
|
||||||
|
_tmp_data = _data
|
||||||
|
# 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 destination Group ID
|
||||||
|
_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
|
||||||
|
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:
|
if rule['DST_TS'] == 0:
|
||||||
_call_info &= ~(1 << 5)
|
_burst_data_type = BURST_DATA_TYPE['SLOT1_VOICE']
|
||||||
elif rule['DST_TS'] == 1:
|
elif rule['DST_TS'] == 1:
|
||||||
_call_info |= 1 << 5
|
_burst_data_type = BURST_DATA_TYPE['SLOT2_VOICE']
|
||||||
_call_info = chr(_call_info)
|
_tmp_data = _tmp_data[:30] + _burst_data_type + _tmp_data[31:]
|
||||||
_tmp_data = _tmp_data[:17] + _call_info + _tmp_data[18:]
|
|
||||||
|
# Calculate and append the authentication hash for the target network... if necessary
|
||||||
# Re-Write DMR timeslot value
|
if NETWORK[_target]['LOCAL']['AUTH_ENABLED']:
|
||||||
# Determine if the slot is present, so we can translate if need be
|
_tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data)
|
||||||
if _burst_data_type == BURST_DATA_TYPE['SLOT1_VOICE'] or _burst_data_type == BURST_DATA_TYPE['SLOT2_VOICE']:
|
# Send the packet to all peers in the target IPSC
|
||||||
_slot_valid = True
|
networks[_target].send_to_ipsc(_tmp_data)
|
||||||
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
|
|
||||||
if NETWORK[_target]['LOCAL']['AUTH_ENABLED']:
|
|
||||||
_tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data)
|
|
||||||
# Send the packet to all peers in the target IPSC
|
|
||||||
networks[_target].send_to_ipsc(_tmp_data)
|
|
||||||
|
|
||||||
# Mark the group and time that a packet was recieved
|
_status[_TS]['TX_GROUP'] = _dst_group
|
||||||
if _ts == 0:
|
_status[_TS]['TX_TIME'] = now
|
||||||
self.ACTIVE_CALLS['TS1'] = _dst_group
|
_status[_TS]['TX_SRC_SUB'] = _src_sub
|
||||||
self.ACTIVE_CALLS['TS1_TIME'] = time()
|
|
||||||
elif _ts == 1:
|
# Mark the group and time that a packet was recieved
|
||||||
self.ACTIVE_CALLS['TS2'] = _dst_group
|
self.IPSC_STATUS[_TS]['RX_GROUP'] = _dst_group
|
||||||
self.ACTIVE_CALLS['TS2_TIME'] = time()
|
self.IPSC_STATUS[_TS]['RX_TIME'] = now
|
||||||
|
|
||||||
else:
|
|
||||||
logger.info('Initializing class methods for standard bridging')
|
|
||||||
class bridgeIPSC(IPSC):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
IPSC.__init__(self, *args, **kwargs)
|
|
||||||
self.ACTIVE_CALLS = {'TS1':0,'TS1_TIME':0,'TS2':0,'TS2_TIME':0}
|
|
||||||
|
|
||||||
|
|
||||||
#************************************************
|
|
||||||
# CALLBACK FUNCTIONS FOR USER PACKET TYPES
|
|
||||||
#************************************************
|
|
||||||
#
|
|
||||||
def group_voice(self, _network, _src_sub, _dst_group, _ts, _end, _peerid, _data):
|
|
||||||
logger.debug('(%s) Group Voice Packet Received From: %s, IPSC Peer %s, Destination %s', _network, int_id(_src_sub), int_id(_peerid), int_id(_dst_group))
|
|
||||||
_burst_data_type = _data[30] # Determine the type of voice packet this is (see top of file for possible types)
|
|
||||||
if _ts:
|
|
||||||
print('GOT PACKET')
|
|
||||||
for rule in RULES[_network]['GROUP_VOICE']:
|
|
||||||
_target = rule['DST_NET'] # Shorthand to reduce length and make it easier to read
|
|
||||||
now = time() # Mark packet arrival time -- we'll need this for call contention handling
|
|
||||||
|
|
||||||
# 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['DST_TS'] == 0:
|
|
||||||
if rule['DST_GROUP'] != self.ACTIVE_CALLS['TS1'] and (now - self.ACTIVE_CALLS['TS1_TIME']) < GROUP_HANG_TIME:
|
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
|
||||||
logger.info('(%s) Call not bridged, already bridging a call to: Destination IPSC %s, TS 1, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
|
||||||
return
|
|
||||||
if ((networks[_target].ACTIVE_CALLS['TS1'] != rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS1_TIME']) < GROUP_HANG_TIME)) \
|
|
||||||
or ((networks[_target].ACTIVE_CALLS['TS1'] == rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS1_TIME']) < TS_CLEAR_TIME)):
|
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
|
||||||
logger.info('(%s) Call not bridged, destination in use: Destination IPSC %s, TS 1, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
|
||||||
return
|
|
||||||
|
|
||||||
if rule['DST_TS'] == 1:
|
|
||||||
if rule['DST_GROUP'] != self.ACTIVE_CALLS['TS2'] and (now - self.ACTIVE_CALLS['TS2_TIME']) < GROUP_HANG_TIME:
|
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
|
||||||
logger.info('(%s) Call not bridged, already bridging a call to: Destination IPSC %s, TS 2, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
|
||||||
return
|
|
||||||
if ((networks[_target].ACTIVE_CALLS['TS2'] != rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS2_TIME']) < GROUP_HANG_TIME)) \
|
|
||||||
or ((networks[_target].ACTIVE_CALLS['TS2'] == rule['DST_GROUP']) and ((now - networks[_target].ACTIVE_CALLS['TS2_TIME']) < TS_CLEAR_TIME)):
|
|
||||||
if _burst_data_type == BURST_DATA_TYPE['VOICE_HEAD']:
|
|
||||||
logger.info('(%s) Call not bridged, destination in use: Destination IPSC %s, TS 2, TGID %s', _network, _target, int_id(rule['DST_GROUP']))
|
|
||||||
return
|
|
||||||
|
|
||||||
_tmp_data = _data
|
|
||||||
# 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 destination Group ID
|
|
||||||
_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
|
|
||||||
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
|
|
||||||
if NETWORK[_target]['LOCAL']['AUTH_ENABLED']:
|
|
||||||
_tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data)
|
|
||||||
# Send the packet to all peers in the target IPSC
|
|
||||||
networks[_target].send_to_ipsc(_tmp_data)
|
|
||||||
|
|
||||||
# Mark the group and time that a packet was recieved
|
|
||||||
if _ts == 0:
|
|
||||||
self.ACTIVE_CALLS['TS1'] = _dst_group
|
|
||||||
self.ACTIVE_CALLS['TS1_TIME'] = time()
|
|
||||||
elif _ts == 1:
|
|
||||||
self.ACTIVE_CALLS['TS2'] = _dst_group
|
|
||||||
self.ACTIVE_CALLS['TS2_TIME'] = time()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@ -317,4 +231,5 @@ if __name__ == '__main__':
|
|||||||
if NETWORK[ipsc_network]['LOCAL']['ENABLED']:
|
if NETWORK[ipsc_network]['LOCAL']['ENABLED']:
|
||||||
networks[ipsc_network] = bridgeIPSC(ipsc_network)
|
networks[ipsc_network] = bridgeIPSC(ipsc_network)
|
||||||
reactor.listenUDP(NETWORK[ipsc_network]['LOCAL']['PORT'], networks[ipsc_network], interface=NETWORK[ipsc_network]['LOCAL']['IP'])
|
reactor.listenUDP(NETWORK[ipsc_network]['LOCAL']['PORT'], networks[ipsc_network], interface=NETWORK[ipsc_network]['LOCAL']['IP'])
|
||||||
|
|
||||||
reactor.run()
|
reactor.run()
|
Loading…
Reference in New Issue
Block a user