From d1f827f1f2ff16e86fa377ce42cedb0942c9c5ec Mon Sep 17 00:00:00 2001 From: Cort Buffington Date: Wed, 26 Sep 2018 15:41:00 -0500 Subject: [PATCH] Revert "Reorganization 1 class per system type" This reverts commit b20309c7767d6120561bf3acf88e8fd86e5e603b. --- hb_config.py | 1 - hblink.py | 173 ++++++++++++++++++++++++--------------------------- 2 files changed, 83 insertions(+), 91 deletions(-) diff --git a/hb_config.py b/hb_config.py index 8633f4c..b892205 100755 --- a/hb_config.py +++ b/hb_config.py @@ -160,7 +160,6 @@ def build_config(_config_file): 'IP': gethostbyname(config.get(section, 'IP')), 'PORT': config.getint(section, 'PORT'), 'PASSPHRASE': config.get(section, 'PASSPHRASE').ljust(20,'\x00')[:20], - 'TARGET_SOCK': (gethostbyname(config.get(section, 'TARGET_IP')), config.getint(section, 'TARGET_PORT')), 'TARGET_IP': gethostbyname(config.get(section, 'TARGET_IP')), 'TARGET_PORT': config.getint(section, 'TARGET_PORT'), }}) diff --git a/hblink.py b/hblink.py index 68fe8d7..e022af8 100755 --- a/hblink.py +++ b/hblink.py @@ -194,33 +194,41 @@ class OPENBRIDGE(DatagramProtocol): self._logger = _logger self._report = _report self._config = self._CONFIG['SYSTEMS'][self._system] + self._localsock = (self._config['IP'], self._config['PORT']) + self._targetsock = (self._config['TARGET_IP'], self._config['TARGET_PORT']) + print(self._config['NETWORK_ID']) def dereg(self): self._logger.info('(%s) is mode OPENBRIDGE. No De-Registration required, continuing shutdown', self._system) def send_system(self, _packet): if _packet[:4] == 'DMRD': - _packet = _packet[:11] + self._config['NETWORK_ID'] + _packet[15:] self.transport.write(_packet, (self._config['TARGET_IP'], self._config['TARGET_PORT'])) - # KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!! - # self._logger.debug('(%s) TX Packet to OpenBridge %s:%s -- %s', self._system, self._config['TARGET_IP'], self._config['TARGET_PORT'], ahex(_packet)) - else: - self._logger.error('(%s) OpenBridge system was asked to send non DMRD packet') def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): pass #print(int_id(_peer_id), int_id(_rf_src), int_id(_dst_id), int_id(_seq), _slot, _call_type, _frame_type, repr(_dtype_vseq), int_id(_stream_id)) + + _dmrd = _data[:53] + _hash = _data[53:] - def datagramReceived(self, _packet, _sockaddr): + _ckhs = hmac_new(self._config['PASSPHRASE'],_dmrd,sha1).digest() + if compare_digest(_hash, _ckhs): + print('PEER:', int_id(_peer_id), 'RF SOURCE:', int_id(_rf_src), 'DESTINATION:', int_id(_dst_id), 'SLOT', _slot, 'SEQ:', int_id(_seq), 'STREAM:', int_id(_stream_id)) + else: + self._logger.info('(%s) OpenBridge HMAC failed, packet discarded', self._system) + + # Aliased in __init__ to datagramReceived if system is a master + def datagramReceived(self, _data, _sockaddr): # Keep This Line Commented Unless HEAVILY Debugging! # self._logger.debug('(%s) RX packet from %s -- %s', self._system, _sockaddr, ahex(_data)) + + # Extract the command, which is various length, all but one 4 significant characters -- RPTCL + _command = _data[:4] - if _packet[:4] == 'DMRD': # DMRData -- encapsulated DMR data frame - _data = _data[:53] - _ckhs = hmac_new(self._config['PASSPHRASE'],_data[53:],sha1).digest() - - if compare_digest(_hash, _ckhs) and _sockaddr == self._config['TARGET_SOCK']: - _peer_id = _data[11:15] + if _command == 'DMRD': # DMRData -- encapsulated DMR data frame + _peer_id = _data[11:15] + if _sockaddr == self._targetsock: _seq = _data[4] _rf_src = _data[5:8] _dst_id = _data[8:11] @@ -234,15 +242,13 @@ class OPENBRIDGE(DatagramProtocol): # Userland actions -- typically this is the function you subclass for an application self.dmrd_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data) - else: - self._logger.info('(%s) OpenBridge HMAC failed, packet discarded', self._system) #************************************************ # HB MASTER CLASS #************************************************ -class HBMASTER(DatagramProtocol): +class HBSYSTEM(DatagramProtocol): def __init__(self, _name, _config, _logger, _report): # Define a few shortcuts to make the rest of the class more readable self._CONFIG = _config @@ -250,7 +256,21 @@ class HBMASTER(DatagramProtocol): self._logger = _logger self._report = _report self._config = self._CONFIG['SYSTEMS'][self._system] - self._peers = self._CONFIG['SYSTEMS'][self._system]['PEERS'] + + # Define shortcuts and generic function names based on the type of system we are + if self._config['MODE'] == 'MASTER': + self._peers = self._CONFIG['SYSTEMS'][self._system]['PEERS'] + self.send_system = self.send_peers + self.maintenance_loop = self.master_maintenance_loop + self.datagramReceived = self.master_datagramReceived + self.dereg = self.master_dereg + + elif self._config['MODE'] == 'PEER': + self._stats = self._config['STATS'] + self.send_system = self.send_master + self.maintenance_loop = self.peer_maintenance_loop + self.datagramReceived = self.peer_datagramReceived + self.dereg = self.peer_dereg # Configure for AMBE audio export if enabled if self._config['EXPORT_AMBE']: @@ -261,7 +281,8 @@ class HBMASTER(DatagramProtocol): self._system_maintenance = task.LoopingCall(self.maintenance_loop) self._system_maintenance_loop = self._system_maintenance.start(self._CONFIG['GLOBAL']['PING_TIME']) - def maintenance_loop(self): + # Aliased in __init__ to maintenance_loop if system is a master + def master_maintenance_loop(self): self._logger.debug('(%s) Master maintenance loop started', self._system) for peer in self._peers: _this_peer = self._peers[peer] @@ -270,8 +291,29 @@ class HBMASTER(DatagramProtocol): self._logger.info('(%s) Peer %s (%s) has timed out', self._system, _this_peer['CALLSIGN'], _this_peer['RADIO_ID']) # Remove any timed out peers from the configuration del self._CONFIG['SYSTEMS'][self._system]['PEERS'][peer] + + # Aliased in __init__ to maintenance_loop if system is a peer + def peer_maintenance_loop(self): + self._logger.debug('(%s) Peer 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 self._stats['CONNECTION'] != 'YES' or self._stats['NUM_OUTSTANDING'] >= self._CONFIG['GLOBAL']['MAX_MISSED']: + self._stats['PINGS_SENT'] = 0 + self._stats['PINGS_ACKD'] = 0 + self._stats['NUM_OUTSTANDING'] = 0 + self._stats['PING_OUTSTANDING'] = False + self._stats['CONNECTION'] = 'RPTL_SENT' + 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']) + # If we are connected, sent a ping to the master and increment the counter + if self._stats['CONNECTION'] == 'YES': + 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['PING_OUTSTANDING'] = True - def send_system(self, _packet): + def send_peers(self, _packet): for _peer in self._peers: self.send_peer(_peer, _packet) #self._logger.debug('(%s) Packet sent to peer %s', self._system, self._peers[_peer]['RADIO_ID']) @@ -281,17 +323,29 @@ class HBMASTER(DatagramProtocol): _packet = _packet[:11] + _peer + _packet[15:] self.transport.write(_packet, self._peers[_peer]['SOCKADDR']) # KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!! - #self._logger.debug('(%s) TX Packet to Peer %s on port %s: %s', self._peers[_peer]['RADIO_ID'], self._peers[_peer]['IP'], self._peers[_peer]['PORT'], ahex(_packet)) - + #self._logger.debug('(%s) TX Packet to %s on port %s: %s', self._peers[_peer]['RADIO_ID'], self._peers[_peer]['IP'], self._peers[_peer]['PORT'], ahex(_packet)) + + def send_master(self, _packet): + if _packet[:4] == 'DMRD': + _packet = _packet[:11] + self._config['RADIO_ID'] + _packet[15:] + self.transport.write(_packet, self._config['MASTER_SOCKADDR']) + # KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!! + # self._logger.debug('(%s) TX Packet to %s:%s -- %s', self._system, self._config['MASTER_IP'], self._config['MASTER_PORT'], ahex(_packet)) + def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): pass - def dereg(self): + def master_dereg(self): for _peer in self._peers: self.send_peer(_peer, 'MSTCL'+_peer) self._logger.info('(%s) De-Registration sent to Peer: %s (%s)', self._system, self._peers[_peer]['CALLSIGN'], self._peers[_peer]['RADIO_ID']) - - def datagramReceived(self, _data, _sockaddr): + + def peer_dereg(self): + self.send_master('RPTCL'+self._config['RADIO_ID']) + self._logger.info('(%s) De-Registration sent to Master: %s:%s', self._system, self._config['MASTER_SOCKADDR'][0], self._config['MASTER_SOCKADDR'][1]) + + # Aliased in __init__ to datagramReceived if system is a master + def master_datagramReceived(self, _data, _sockaddr): # Keep This Line Commented Unless HEAVILY Debugging! # self._logger.debug('(%s) RX packet from %s -- %s', self._system, _sockaddr, ahex(_data)) @@ -443,65 +497,8 @@ class HBMASTER(DatagramProtocol): else: self._logger.error('(%s) Unrecognized command. Raw HBP PDU: %s', self._system, ahex(_data)) - -#************************************************ -# HB PEER CLASS -#************************************************ - -class HBPEER(DatagramProtocol): - def __init__(self, _name, _config, _logger, _report): - # Define a few shortcuts to make the rest of the class more readable - self._CONFIG = _config - self._system = _name - self._logger = _logger - self._report = _report - self._config = self._CONFIG['SYSTEMS'][self._system] - self._stats = self._config['STATS'] - - # Configure for AMBE audio export if enabled - if self._config['EXPORT_AMBE']: - self._ambe = AMBE(_config, _logger) - - def startProtocol(self): - # Set up periodic loop for tracking pings from peers. Run every 'PING_TIME' seconds - self._system_maintenance = task.LoopingCall(self.maintenance_loop) - self._system_maintenance_loop = self._system_maintenance.start(self._CONFIG['GLOBAL']['PING_TIME']) - - def maintenance_loop(self): - self._logger.debug('(%s) Peer 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 self._stats['CONNECTION'] != 'YES' or self._stats['NUM_OUTSTANDING'] >= self._CONFIG['GLOBAL']['MAX_MISSED']: - self._stats['PINGS_SENT'] = 0 - self._stats['PINGS_ACKD'] = 0 - self._stats['NUM_OUTSTANDING'] = 0 - self._stats['PING_OUTSTANDING'] = False - self._stats['CONNECTION'] = 'RPTL_SENT' - self.send_system('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']) - # If we are connected, sent a ping to the master and increment the counter - if self._stats['CONNECTION'] == 'YES': - self.send_system('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['PING_OUTSTANDING'] = True - - def send_system(self, _packet): - if _packet[:4] == 'DMRD': - _packet = _packet[:11] + self._config['RADIO_ID'] + _packet[15:] - self.transport.write(_packet, self._config['MASTER_SOCKADDR']) - # KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!! - # self._logger.debug('(%s) TX Packet to Master %s:%s -- %s', self._system, self._config['MASTER_IP'], self._config['MASTER_PORT'], ahex(_packet)) - - def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): - pass - - def dereg(self): - self.send_system('RPTCL'+self._config['RADIO_ID']) - self._logger.info('(%s) De-Registration sent to Master: %s:%s', self._system, self._config['MASTER_SOCKADDR'][0], self._config['MASTER_SOCKADDR'][1]) - - def datagramReceived(self, _data, _sockaddr): + # Aliased in __init__ to datagramReceived if system is a peer + def peer_datagramReceived(self, _data, _sockaddr): # Keep This Line Commented Unless HEAVILY Debugging! # self._logger.debug('(%s) RX packet from %s -- %s', self._system, _sockaddr, ahex(_data)) @@ -543,7 +540,7 @@ class HBPEER(DatagramProtocol): 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 = bhex(_pass_hash) - self.send_system('RPTK'+self._config['RADIO_ID']+_pass_hash) + self.send_master('RPTK'+self._config['RADIO_ID']+_pass_hash) self._stats['CONNECTION'] = 'AUTHENTICATED' elif self._stats['CONNECTION'] == 'AUTHENTICATED': # If we've sent the login challenge... @@ -566,7 +563,7 @@ class HBPEER(DatagramProtocol): self._config['SOFTWARE_ID']+\ self._config['PACKAGE_ID'] - self.send_system('RPTC'+_config_packet) + self.send_master('RPTC'+_config_packet) self._stats['CONNECTION'] = 'CONFIG-SENT' self._logger.info('(%s) Repeater Configuration Sent', self._system) else: @@ -578,7 +575,7 @@ class HBPEER(DatagramProtocol): if self._config['LOOSE'] or _peer_id == self._config['RADIO_ID']: # Validate the Radio_ID unless using loose validation self._logger.info('(%s) Repeater Configuration Accepted', self._system) if self._config['OPTIONS']: - self.send_system('RPTO'+self._config['RADIO_ID']+self._config['OPTIONS']) + self.send_master('RPTO'+self._config['RADIO_ID']+self._config['OPTIONS']) self._stats['CONNECTION'] = 'OPTIONS-SENT' self._logger.info('(%s) Sent options: (%s)', self._system, self._config['OPTIONS']) else: @@ -720,12 +717,8 @@ if __name__ == '__main__': if CONFIG['SYSTEMS'][system]['ENABLED']: if CONFIG['SYSTEMS'][system]['MODE'] == 'OPENBRIDGE': systems[system] = OPENBRIDGE(system, CONFIG, logger, report_server) - elif CONFIG['SYSTEMS'][system]['MODE'] == 'MASTER': - systems[system] = HBMASTER(system, CONFIG, logger, report_server) - elif CONFIG['SYSTEMS'][system]['MODE'] == 'PEER': - systems[system] = HBPEER(system, CONFIG, logger, report_server) else: - logger.error('%s instance error: %s, %s. No such MODE: %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system], CONFIG['SYSTEMS'][system]['MODE']) + systems[system] = HBSYSTEM(system, CONFIG, logger, report_server) 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])