HIGH PROFILE FIXES - Addresses Brandmeister disconnects.
Random: * Commented out per-packet debug logger lines (uncomment locally when needed) Problems Fixed: CLIENT MODE: hblink.py hblink.py did not properly parse the radio_id in a MSTNAK message. We searched for "MSTN" - 4 characters, and neglected to parse the radio ID at offset 6, after "MSTNAK" instead of after 4, "MSTN".... rookie mistake: elif _command == 'MSTN': # Actually MSTNAK -- a NACK from the master - _radio_id = _data[4:8] + _radio_id = _data[6:10] hblink.py did not actually keep track of missed keep-alives correctly to reset a connection. This has probably been fixed. At worst, no more broken than it was. Would like to have some folks test it by breaking connectivty froma client to master and watch what happens. Appears to work now.
This commit is contained in:
parent
382d594adf
commit
050aad7cb3
@ -134,7 +134,7 @@ class bridgeallSYSTEM(HBSYSTEM):
|
|||||||
for _target in self._CONFIG['SYSTEMS']:
|
for _target in self._CONFIG['SYSTEMS']:
|
||||||
if _target != self._system:
|
if _target != self._system:
|
||||||
systems[_target].send_system(_data)
|
systems[_target].send_system(_data)
|
||||||
self._logger.debug('(%s) Packet routed to system: %s', self._system, _target)
|
#self._logger.debug('(%s) Packet routed to system: %s', self._system, _target)
|
||||||
|
|
||||||
|
|
||||||
# Final actions - Is this a voice terminator?
|
# Final actions - Is this a voice terminator?
|
||||||
@ -228,4 +228,4 @@ if __name__ == '__main__':
|
|||||||
reactor.listenUDP(CONFIG['SYSTEMS'][system]['PORT'], systems[system], interface=CONFIG['SYSTEMS'][system]['IP'])
|
reactor.listenUDP(CONFIG['SYSTEMS'][system]['PORT'], systems[system], interface=CONFIG['SYSTEMS'][system]['IP'])
|
||||||
logger.debug('%s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system])
|
logger.debug('%s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system])
|
||||||
|
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
@ -121,6 +121,7 @@ def build_config(_config_file):
|
|||||||
'CONNECTION': 'NO', # NO, RTPL_SENT, AUTHENTICATED, CONFIG-SENT, YES
|
'CONNECTION': 'NO', # NO, RTPL_SENT, AUTHENTICATED, CONFIG-SENT, YES
|
||||||
'PINGS_SENT': 0,
|
'PINGS_SENT': 0,
|
||||||
'PINGS_ACKD': 0,
|
'PINGS_ACKD': 0,
|
||||||
|
'NUM_OUTSTANDING': 0,
|
||||||
'PING_OUTSTANDING': False,
|
'PING_OUTSTANDING': False,
|
||||||
'LAST_PING_TX_TIME': 0,
|
'LAST_PING_TX_TIME': 0,
|
||||||
'LAST_PING_ACK_TIME': 0,
|
'LAST_PING_ACK_TIME': 0,
|
||||||
|
21
hblink.py
21
hblink.py
@ -154,18 +154,23 @@ class HBSYSTEM(DatagramProtocol):
|
|||||||
# Aliased in __init__ to maintenance_loop if system is a client
|
# Aliased in __init__ to maintenance_loop if system is a client
|
||||||
def client_maintenance_loop(self):
|
def client_maintenance_loop(self):
|
||||||
self._logger.debug('(%s) Client maintenance loop started', self._system)
|
self._logger.debug('(%s) Client maintenance loop started', self._system)
|
||||||
|
if self._stats['PING_OUTSTANDING']:
|
||||||
|
self._stats['NUM_OUTSTANDING'] += 1
|
||||||
# If we're not connected, zero out the stats and send a login request RPTL
|
# If we're not connected, zero out the stats and send a login request RPTL
|
||||||
if self._stats['CONNECTION'] == 'NO' or self._stats['CONNECTION'] == 'RTPL_SENT':
|
if self._stats['CONNECTION'] == 'NO' or self._stats['CONNECTION'] == 'RPTL_SENT' or self._stats['NUM_OUTSTANDING'] >= self._CONFIG['GLOBAL']['MAX_MISSED']:
|
||||||
self._stats['PINGS_SENT'] = 0
|
self._stats['PINGS_SENT'] = 0
|
||||||
self._stats['PINGS_ACKD'] = 0
|
self._stats['PINGS_ACKD'] = 0
|
||||||
self._stats['CONNECTION'] = 'RTPL_SENT'
|
self._stats['NUM_OUTSTANDING'] = 0
|
||||||
|
self._stats['PING_OUTSTANDING'] = False
|
||||||
|
self._stats['CONNECTION'] = 'RPTL_SENT'
|
||||||
self.send_master('RPTL'+self._config['RADIO_ID'])
|
self.send_master('RPTL'+self._config['RADIO_ID'])
|
||||||
self._logger.info('(%s) Sending login request to master %s:%s', self._system, self._config['MASTER_IP'], self._config['MASTER_PORT'])
|
self._logger.info('(%s) Sending login request to master %s:%s', self._system, self._config['MASTER_IP'], self._config['MASTER_PORT'])
|
||||||
# If we are connected, sent a ping to the master and increment the counter
|
# If we are connected, sent a ping to the master and increment the counter
|
||||||
if self._stats['CONNECTION'] == 'YES':
|
if self._stats['CONNECTION'] == 'YES':
|
||||||
self.send_master('RPTPING'+self._config['RADIO_ID'])
|
self.send_master('RPTPING'+self._config['RADIO_ID'])
|
||||||
|
self._logger.debug('(%s) RPTPING Sent to Master. Total Sent: %s, Total Missed: %s, Currently Outstanding: %s', self._system, self._stats['PINGS_SENT'], self._stats['PINGS_SENT'] - self._stats['PINGS_ACKD'], self._stats['NUM_OUTSTANDING'])
|
||||||
self._stats['PINGS_SENT'] += 1
|
self._stats['PINGS_SENT'] += 1
|
||||||
self._logger.debug('(%s) RPTPING Sent to Master. Pings Since Connected: %s', self._system, self._stats['PINGS_SENT'])
|
self._stats['PING_OUTSTANDING'] = True
|
||||||
|
|
||||||
def send_clients(self, _packet):
|
def send_clients(self, _packet):
|
||||||
for _client in self._clients:
|
for _client in self._clients:
|
||||||
@ -230,7 +235,7 @@ class HBSYSTEM(DatagramProtocol):
|
|||||||
for _client in self._clients:
|
for _client in self._clients:
|
||||||
if _client != _radio_id:
|
if _client != _radio_id:
|
||||||
self.send_client(_client, _data)
|
self.send_client(_client, _data)
|
||||||
self._logger.debug('(%s) Packet on TS%s from %s (%s) for destination ID %s repeated to client: %s (%s) [Stream ID: %s]', self._system, _slot, self._clients[_radio_id]['CALLSIGN'], int_id(_radio_id), int_id(_dst_id), self._clients[_client]['CALLSIGN'], int_id(_client), int_id(_stream_id))
|
#self._logger.debug('(%s) Packet on TS%s from %s (%s) for destination ID %s repeated to client: %s (%s) [Stream ID: %s]', self._system, _slot, self._clients[_radio_id]['CALLSIGN'], int_id(_radio_id), int_id(_dst_id), self._clients[_client]['CALLSIGN'], int_id(_client), int_id(_stream_id))
|
||||||
|
|
||||||
# Userland actions -- typically this is the function you subclass for an application
|
# Userland actions -- typically this is the function you subclass for an application
|
||||||
self.dmrd_received(_radio_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
|
self.dmrd_received(_radio_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
|
||||||
@ -381,14 +386,14 @@ class HBSYSTEM(DatagramProtocol):
|
|||||||
self.dmrd_received(_radio_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
|
self.dmrd_received(_radio_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
|
||||||
|
|
||||||
elif _command == 'MSTN': # Actually MSTNAK -- a NACK from the master
|
elif _command == 'MSTN': # Actually MSTNAK -- a NACK from the master
|
||||||
_radio_id = _data[4:8]
|
_radio_id = _data[6:10]
|
||||||
if _radio_id == self._config['RADIO_ID']: # Validate the source and intended target
|
if _radio_id == self._config['RADIO_ID']: # Validate the source and intended target
|
||||||
self._logger.warning('(%s) MSTNAK Received', self._system)
|
self._logger.warning('(%s) MSTNAK Received. Resetting connection to the Master.', self._system)
|
||||||
self._stats['CONNECTION'] = 'NO' # Disconnect ourselves and re-register
|
self._stats['CONNECTION'] = 'NO' # Disconnect ourselves and re-register
|
||||||
|
|
||||||
elif _command == 'RPTA': # Actually RPTACK -- an ACK from the master
|
elif _command == 'RPTA': # Actually RPTACK -- an ACK from the master
|
||||||
# Depending on the state, an RPTACK means different things, in each clause, we check and/or set the state
|
# Depending on the state, an RPTACK means different things, in each clause, we check and/or set the state
|
||||||
if self._stats['CONNECTION'] == 'RTPL_SENT': # If we've sent a login request...
|
if self._stats['CONNECTION'] == 'RPTL_SENT': # If we've sent a login request...
|
||||||
_login_int32 = _data[6:10]
|
_login_int32 = _data[6:10]
|
||||||
self._logger.info('(%s) Repeater Login ACK Received with 32bit ID: %s', self._system, int_id(_login_int32))
|
self._logger.info('(%s) Repeater Login ACK Received with 32bit ID: %s', self._system, int_id(_login_int32))
|
||||||
_pass_hash = sha256(_login_int32+self._config['PASSPHRASE']).hexdigest()
|
_pass_hash = sha256(_login_int32+self._config['PASSPHRASE']).hexdigest()
|
||||||
@ -447,6 +452,8 @@ class HBSYSTEM(DatagramProtocol):
|
|||||||
|
|
||||||
elif _command == 'MSTP': # Actually MSTPONG -- a reply to RPTPING (send by client)
|
elif _command == 'MSTP': # Actually MSTPONG -- a reply to RPTPING (send by client)
|
||||||
if _data [7:11] == self._config['RADIO_ID']:
|
if _data [7:11] == self._config['RADIO_ID']:
|
||||||
|
self._stats['PING_OUTSTANDING'] = False
|
||||||
|
self._stats['NUM_OUTSTANDING'] = 0
|
||||||
self._stats['PINGS_ACKD'] += 1
|
self._stats['PINGS_ACKD'] += 1
|
||||||
self._logger.debug('(%s) MSTPONG Received. Pongs Since Connected: %s', self._system, self._stats['PINGS_ACKD'])
|
self._logger.debug('(%s) MSTPONG Received. Pongs Since Connected: %s', self._system, self._stats['PINGS_ACKD'])
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user