Name Change - Function Re-Org

Preparing to use DMRlink as a python module. The name needed to be
changed to not clash with the resource sub-directory, and functions
were moved into the main class that are intended to be changed in a
derived class.

DMRlink is now a functional module. I will be shifting ALL development
of "application" level features to other files with derived classes,
and dmrlink.py will ONLY include protocol update/fixes/etc.
This commit is contained in:
Cort Buffington 2013-10-28 20:34:29 -05:00
parent 3cb242d368
commit 9f53e7035b
1 changed files with 155 additions and 149 deletions

View File

@ -46,7 +46,6 @@ try:
from ipsc.ipsc_mask import *
except ImportError:
sys.exit('IPSC mask values file not found or invalid')
ids = {}
try:
@ -91,152 +90,68 @@ except ImportError:
.... ...x = Set if master
'''
ACTIVE_CALLS = []
networks = {}
NETWORK = {}
config = ConfigParser.ConfigParser()
config.read('./dmrlink.cfg')
for section in config.sections():
NETWORK.update({section: {'LOCAL': {}, 'MASTER': {}, 'PEERS': []}})
NETWORK[section]['LOCAL'].update({
'MODE': '',
'PEER_OPER': True,
'PEER_MODE': 'DIGITAL',
'FLAGS': '',
'MAX_MISSED': 10,
'NUM_PEERS': 0,
'STATUS': {
'ACTIVE': False
if section == 'GLOBAL':
pass
else:
NETWORK.update({section: {'LOCAL': {}, 'MASTER': {}, 'PEERS': []}})
NETWORK[section]['LOCAL'].update({
'MODE': '',
'PEER_OPER': True,
'PEER_MODE': 'DIGITAL',
'FLAGS': '',
'MAX_MISSED': 10,
'NUM_PEERS': 0,
'STATUS': {
'ACTIVE': False
},
'ENABLED': config.getboolean(section, 'ENABLED'),
'TS1_LINK': config.getboolean(section, 'TS1_LINK'),
'TS2_LINK': config.getboolean(section, 'TS2_LINK'),
'AUTH_ENABLED': config.getboolean(section, 'AUTH_ENABLED'),
'RADIO_ID': (config.get(section, 'RADIO_ID').rjust(8,'0')).decode('hex'),
'PORT': config.getint(section, 'PORT'),
'ALIVE_TIMER': config.getint(section, 'ALIVE_TIMER'),
'AUTH_KEY': (config.get(section, 'AUTH_KEY').rjust(40,'0')).decode('hex'),
})
NETWORK[section]['MASTER'].update({
'RADIO_ID': '\x00\x00\x00\x00',
'MODE': '\x00',
'PEER_OPER': False,
'PEER_MODE': '',
'TS1_LINK': False,
'TS2_LINK': False,
'FLAGS': '\x00\x00\x00\x00',
'STATUS': {
'CONNECTED': False,
'PEER-LIST': False,
'KEEP_ALIVES_SENT': 0,
'KEEP_ALIVES_MISSED': 0,
'KEEP_ALIVES_OUTSTANDING': 0
},
'ENABLED': config.getboolean(section, 'ENABLED'),
'TS1_LINK': config.getboolean(section, 'TS1_LINK'),
'TS2_LINK': config.getboolean(section, 'TS2_LINK'),
'AUTH_ENABLED': config.getboolean(section, 'AUTH_ENABLED'),
'RADIO_ID': (config.get(section, 'RADIO_ID').rjust(8,'0')).decode('hex'),
'PORT': config.getint(section, 'PORT'),
'ALIVE_TIMER': config.getint(section, 'ALIVE_TIMER'),
'AUTH_KEY': (config.get(section, 'AUTH_KEY').rjust(40,'0')).decode('hex'),
})
NETWORK[section]['MASTER'].update({
'RADIO_ID': '\x00\x00\x00\x00',
'MODE': '\x00',
'PEER_OPER': False,
'PEER_MODE': '',
'TS1_LINK': False,
'TS2_LINK': False,
'FLAGS': '\x00\x00\x00\x00',
'STATUS': {
'CONNECTED': False,
'PEER-LIST': False,
'KEEP_ALIVES_SENT': 0,
'KEEP_ALIVES_MISSED': 0,
'KEEP_ALIVES_OUTSTANDING': 0
},
'IP': config.get(section, 'MASTER_IP'),
'PORT': config.getint(section, 'MASTER_PORT')
})
'IP': config.get(section, 'MASTER_IP'),
'PORT': config.getint(section, 'MASTER_PORT')
})
if NETWORK[section]['LOCAL']['AUTH_ENABLED']:
NETWORK[section]['LOCAL']['FLAGS'] = '\x00\x00\x00\x1C'
else:
NETWORK[section]['LOCAL']['FLAGS'] = '\x00\x00\x00\x0C'
if NETWORK[section]['LOCAL']['AUTH_ENABLED']:
NETWORK[section]['LOCAL']['FLAGS'] = '\x00\x00\x00\x1C'
else:
NETWORK[section]['LOCAL']['FLAGS'] = '\x00\x00\x00\x0C'
if not NETWORK[section]['LOCAL']['TS1_LINK'] and not NETWORK[section]['LOCAL']['TS2_LINK']:
NETWORK[section]['LOCAL']['MODE'] = '\x65'
elif NETWORK[section]['LOCAL']['TS1_LINK'] and not NETWORK[section]['LOCAL']['TS2_LINK']:
NETWORK[section]['LOCAL']['MODE'] = '\x66'
elif not NETWORK[section]['LOCAL']['TS1_LINK'] and NETWORK[section]['LOCAL']['TS2_LINK']:
NETWORK[section]['LOCAL']['MODE'] = '\x69'
else:
NETWORK[section]['LOCAL']['MODE'] = '\x6A'
#************************************************
# CALLBACK FUNCTIONS FOR USER PACKET TYPES
#************************************************
def call_ctl_1(_network, _data):
print('({}) Call Control Type 1 Packet Received From: {}' .format(_network, _src_sub))
def call_ctl_2(_network, _data):
print('({}) Call Control Type 2 Packet Received' .format(_network))
def call_ctl_3(_network, _data):
print('({}) Call Control Type 3 Packet Received' .format(_network))
def xcmp_xnl(_network, _data):
print('({}) XCMP/XNL Packet Received From: {}' .format(_network, _src_sub))
def group_voice(_network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
# _log = logger.debug
if ((_network, _ts) not in ACTIVE_CALLS) or _end:
_time = time.strftime('%m/%d/%y %H:%M:%S')
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
if not _end: ACTIVE_CALLS.append((_network, _ts))
if _end: ACTIVE_CALLS.remove((_network, _ts))
if _ts: _ts = 2
else: _ts = 1
if _end: _end = 'END'
else: _end = 'START'
print('{} ({}) Call {} Group Voice: \n\tIPSC Source:\t{}\n\tSubscriber:\t{}\n\tDestination:\t{}\n\tTimeslot\t{}' .format(_time, _network, _end, _peerid, _src_sub, _dst_sub, _ts))
'''
for source in NETWORK[_network]['RULES']['GROUP_VOICE']:
# Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP)
if source['SRC_GROUP'] == _src_group:
_target = source['DST_NET']
_target_sock = NETWORK[_target]['MASTER']['IP'], NETWORK[_target]['MASTER']['PORT']
# Re-Write the IPSC SRC to match the target network's ID
_data = _data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID'])
# Re-Write the destinaion Group ID
_data = _data.replace(_src_group, source['DST_GROUP'])
# Calculate and append the authentication hash for the target network... if necessary
if NETWORK[_target]['LOCAL']['AUTH_KEY'] == True:
_data = hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _data)
# Send the packet to all peers in the target IPSC
send_to_ipsc(_target, _data)
'''
def private_voice(_network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
# _log = logger.debug
if ((_network, _ts) not in ACTIVE_CALLS) or _end:
_time = time.strftime('%m/%d/%y %H:%M:%S')
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
if not _end: ACTIVE_CALLS.append((_network, _ts))
if _end: ACTIVE_CALLS.remove((_network, _ts))
if _ts: _ts = 2
else: _ts = 1
if _end: _end = 'END'
else: _end = 'START'
print('{} ({}) Call {} Private Voice: \n\tIPSC Source:\t{}\n\tSubscriber:\t{}\n\tDestination:\t{}\n\tTimeslot\t{}' .format(_time, _network, _end, _peerid, _src_sub, _dst_sub, _ts))
def group_data(_network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
print('({}) Group Data Packet Received From: {}' .format(_network, _src_sub))
def private_data(_network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
print('({}) Private Data Packet Received From: {} To: {}' .format(_network, _src_sub, _dst_sub))
def unknown_message(_network, _packettype, _peerid, _data):
_time = time.strftime('%m/%d/%y %H:%M:%S')
_packettype = binascii.b2a_hex(_packettype)
_peerid = get_info(int_id(_peerid))
print('{} ({}) Unknown message type encountered\n\tPacket Type: {}\n\tFrom: {}' .format(_time, _network, _packettype, _peerid))
print('\t', binascii.b2a_hex(_data))
if not NETWORK[section]['LOCAL']['TS1_LINK'] and not NETWORK[section]['LOCAL']['TS2_LINK']:
NETWORK[section]['LOCAL']['MODE'] = '\x65'
elif NETWORK[section]['LOCAL']['TS1_LINK'] and not NETWORK[section]['LOCAL']['TS2_LINK']:
NETWORK[section]['LOCAL']['MODE'] = '\x66'
elif not NETWORK[section]['LOCAL']['TS1_LINK'] and NETWORK[section]['LOCAL']['TS2_LINK']:
NETWORK[section]['LOCAL']['MODE'] = '\x69'
else:
NETWORK[section]['LOCAL']['MODE'] = '\x6A'
#************************************************
@ -478,9 +393,14 @@ class IPSC(DatagramProtocol):
# Spendy than iterating a list of dictionaries... Maybe I'll find a better way in the future. Also
# We have to know when we have a new peer list, so a variable to indicate we do (or don't)
#
self._peer_list = []
self._peer_list = []
#
# A place to keep track of calls that are active on this IPSC
self.ACTIVE_CALLS = []
args = ()
# Packet 'constructors' - builds the necessary control packets for this IPSC instance.
# This isn't really necessary for anything other than readability (reduction of code golf)
#
@ -514,6 +434,92 @@ class IPSC(DatagramProtocol):
self._reporting = task.LoopingCall(self.reporting_loop)
self._reporting_loop = self._reporting.start(10)
#************************************************
# CALLBACK FUNCTIONS FOR USER PACKET TYPES
#************************************************
def call_ctl_1(self, _network, _data):
print('({}) Call Control Type 1 Packet Received From: {}' .format(_network, _src_sub))
def call_ctl_2(self, _network, _data):
print('({}) Call Control Type 2 Packet Received' .format(_network))
def call_ctl_3(self, _network, _data):
print('({}) Call Control Type 3 Packet Received' .format(_network))
def xcmp_xnl(self, _network, _data):
print('({}) XCMP/XNL Packet Received From: {}' .format(_network, _src_sub))
def group_voice(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
# _log = logger.debug
if (_ts not in self.ACTIVE_CALLS) or _end:
_time = time.strftime('%m/%d/%y %H:%M:%S')
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
if not _end: self.ACTIVE_CALLS.append(_ts)
if _end: self.ACTIVE_CALLS.remove(_ts)
if _ts: _ts = 2
else: _ts = 1
if _end: _end = 'END'
else: _end = 'START'
print('{} ({}) Call {} Group Voice: \n\tIPSC Source:\t{}\n\tSubscriber:\t{}\n\tDestination:\t{}\n\tTimeslot\t{}' .format(_time, _network, _end, _peerid, _src_sub, _dst_sub, _ts))
'''
for source in NETWORK[_network]['RULES']['GROUP_VOICE']:
# Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP)
if source['SRC_GROUP'] == _src_group:
_target = source['DST_NET']
_target_sock = NETWORK[_target]['MASTER']['IP'], NETWORK[_target]['MASTER']['PORT']
# Re-Write the IPSC SRC to match the target network's ID
_data = _data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID'])
# Re-Write the destinaion Group ID
_data = _data.replace(_src_group, source['DST_GROUP'])
# Calculate and append the authentication hash for the target network... if necessary
if NETWORK[_target]['LOCAL']['AUTH_KEY'] == True:
_data = hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _data)
# Send the packet to all peers in the target IPSC
send_to_ipsc(_target, _data)
'''
def private_voice(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
# _log = logger.debug
if ((_network, _ts) not in self.ACTIVE_CALLS) or _end:
_time = time.strftime('%m/%d/%y %H:%M:%S')
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
if not _end: self.ACTIVE_CALLS.append((_network, _ts))
if _end: self.ACTIVE_CALLS.remove((_network, _ts))
if _ts: _ts = 2
else: _ts = 1
if _end: _end = 'END'
else: _end = 'START'
print('{} ({}) Call {} Private Voice: \n\tIPSC Source:\t{}\n\tSubscriber:\t{}\n\tDestination:\t{}\n\tTimeslot\t{}' .format(_time, _network, _end, _peerid, _src_sub, _dst_sub, _ts))
def group_data(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
print('({}) Group Data Packet Received From: {}' .format(_network, _src_sub))
def private_data(self, _network, _src_sub, _dst_sub, _ts, _end, _peerid, _data):
_dst_sub = get_info(int_id(_dst_sub))
_peerid = get_info(int_id(_peerid))
_src_sub = get_info(int_id(_src_sub))
print('({}) Private Data Packet Received From: {} To: {}' .format(_network, _src_sub, _dst_sub))
def unknown_message(self, _network, _packettype, _peerid, _data):
_time = time.strftime('%m/%d/%y %H:%M:%S')
_packettype = binascii.b2a_hex(_packettype)
_peerid = get_info(int_id(_peerid))
print('{} ({}) Unknown message type encountered\n\tPacket Type: {}\n\tFrom: {}' .format(_time, _network, _packettype, _peerid))
print('\t', binascii.b2a_hex(_data))
# Take a packet to be SENT, calcualte auth hash and return the whole thing
#
@ -675,40 +681,40 @@ class IPSC(DatagramProtocol):
# User Voice and Data Call Types:
if (_packettype == GROUP_VOICE):
self._notify_event(self._network, 'group_voice', {'peer_id': int(binascii.b2a_hex(_peerid), 16)})
group_voice(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
self.group_voice(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
return
elif (_packettype == PVT_VOICE):
self._notify_event(self._network, 'private_voice', {'peer_id': int(binascii.b2a_hex(_peerid), 16)})
private_voice(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
self.private_voice(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
return
elif (_packettype == GROUP_DATA):
self._notify_event(self._network, 'group_data', {'peer_id': int(binascii.b2a_hex(_peerid), 16)})
group_data(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
self.group_data(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
return
elif (_packettype == PVT_DATA):
self._notify_event(self._network, 'private_voice', {'peer_id': int(binascii.b2a_hex(_peerid), 16)})
private_data(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
self.private_data(self._network, _src_sub, _dst_sub, _ts, _end, _peerid, data)
return
return
# Other peer-required types that we don't do much or anything with yet
elif (_packettype == XCMP_XNL):
xcmp_xnl(self._network, data)
self.xcmp_xnl(self._network, data)
return
elif (_packettype == CALL_CTL_1):
call_ctl_1(self._network, data)
self.call_ctl_1(self._network, data)
return
elif (_packettype == CALL_CTL_2):
call_ctl_2(self._network, data)
self.call_ctl_2(self._network, data)
return
elif (_packettype == CALL_CTL_3):
call_ctl_3(self._network, data)
self.call_ctl_3(self._network, data)
return
# Connection maintenance packets that fall into this category
@ -795,7 +801,7 @@ class IPSC(DatagramProtocol):
# If there's a packet type we don't know aobut, it should be logged so we can figure it out and take an appropriate action!
else:
unknown_message(self._network, _packettype, _peerid, data)
self.unknown_message(self._network, _packettype, _peerid, data)
return
@ -823,7 +829,7 @@ class UnauthIPSC(IPSC):
#************************************************
if __name__ == '__main__':
networks = {}
#networks = {}
for ipsc_network in NETWORK:
if (NETWORK[ipsc_network]['LOCAL']['ENABLED']):
if NETWORK[ipsc_network]['LOCAL']['AUTH_ENABLED'] == True: