BEGIN working on bridge code
Stopped with this not completed, but mostly there. Need to fix some references.
This commit is contained in:
parent
365f752c8e
commit
1dc2dc0081
79
ipsc.py
79
ipsc.py
@ -105,6 +105,23 @@ def validate_auth(_key, _data):
|
|||||||
_log(' AUTH: Invalid - Payload: %s, Hash: %s', binascii.b2a_hex(_payload), binascii.b2a_hex(_hash))
|
_log(' AUTH: Invalid - Payload: %s, Hash: %s', binascii.b2a_hex(_payload), binascii.b2a_hex(_hash))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Forward Group Voice Packet
|
||||||
|
# THIS IS BROKEN - BEGIN WORK HERE. REPLACING SEGMENTS ISN'T REFERENCING THE RIGHT SUBSTITUTE DATA AND
|
||||||
|
# I'M GOIGN TO BED NOW.
|
||||||
|
def fwd_group_voice(_network, _data):
|
||||||
|
_src_group = _data[9:12]
|
||||||
|
_src_ipsc = _data[1:5]
|
||||||
|
for source in NETWORK[_network]['GROUP_VOICE']:
|
||||||
|
print(binascii.b2a_hex(_src_group), ' ', binascii.b2a_hex(source['SRC_GROUP']))
|
||||||
|
if source['SRC_GROUP'] == _src_group:
|
||||||
|
_data.replace(_src_ipsc, NETWORK[source]['DST_NET']['LOCAL']['RADIO_ID'])
|
||||||
|
_data.replace(_src_group, source['DST_GROUP'])
|
||||||
|
_data = hashed_packet(NETWORK[source]['DST_NET']['LOCAL']['AUTH_KEY'], _data)
|
||||||
|
print(binascii.b2a_hex(_data))
|
||||||
|
# Match source group to a rule
|
||||||
|
# Write destination group to packet
|
||||||
|
# Hash packet
|
||||||
|
# Send packet
|
||||||
|
|
||||||
# Take a recieved peer list and the network it belongs to, process and populate the
|
# Take a recieved peer list and the network it belongs to, process and populate the
|
||||||
# data structure in my_ipsc_config with the results.
|
# data structure in my_ipsc_config with the results.
|
||||||
@ -238,7 +255,12 @@ class IPSC(DatagramProtocol):
|
|||||||
#
|
#
|
||||||
self._peers = self._config['PEERS']
|
self._peers = self._config['PEERS']
|
||||||
#
|
#
|
||||||
|
# This is a regular list to store peers for the IPSC. At times, parsing a simple list is much less
|
||||||
|
# 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 = []
|
||||||
|
self._peer_list_new = False
|
||||||
|
|
||||||
args = ()
|
args = ()
|
||||||
|
|
||||||
@ -252,7 +274,7 @@ class IPSC(DatagramProtocol):
|
|||||||
self.PEER_REG_REPLY_PKT = (PEER_REG_REPLY + self._local_id + IPSC_VER)
|
self.PEER_REG_REPLY_PKT = (PEER_REG_REPLY + self._local_id + IPSC_VER)
|
||||||
self.PEER_ALIVE_REQ_PKT = (PEER_ALIVE_REQ + self._local_id + self.TS_FLAGS)
|
self.PEER_ALIVE_REQ_PKT = (PEER_ALIVE_REQ + self._local_id + self.TS_FLAGS)
|
||||||
self.PEER_ALIVE_REPLY_PKT = (PEER_ALIVE_REPLY + self._local_id + self.TS_FLAGS)
|
self.PEER_ALIVE_REPLY_PKT = (PEER_ALIVE_REPLY + self._local_id + self.TS_FLAGS)
|
||||||
self._peer_list_new = False
|
|
||||||
else:
|
else:
|
||||||
# If we didn't get called correctly, log it!
|
# If we didn't get called correctly, log it!
|
||||||
#
|
#
|
||||||
@ -278,20 +300,15 @@ class IPSC(DatagramProtocol):
|
|||||||
# TIMED LOOP - MY CONNECTION MAINTENANCE
|
# TIMED LOOP - MY CONNECTION MAINTENANCE
|
||||||
#************************************************
|
#************************************************
|
||||||
|
|
||||||
def timed_loop(self):
|
def timed_loop(self):
|
||||||
logger.debug('timed loop started') # temporary debugging to make sure this part runs
|
|
||||||
|
|
||||||
print_peer_list(self._network)
|
print_peer_list(self._network)
|
||||||
|
|
||||||
_master_connected = self._master_stat['CONNECTED']
|
|
||||||
_peer_list_rx = self._master_stat['PEER-LIST']
|
|
||||||
|
|
||||||
if (_master_connected == False):
|
if (self._master_stat['CONNECTED'] == False):
|
||||||
reg_packet = hashed_packet(self._local['AUTH_KEY'], self.MASTER_REG_REQ_PKT)
|
reg_packet = hashed_packet(self._local['AUTH_KEY'], self.MASTER_REG_REQ_PKT)
|
||||||
self.transport.write(reg_packet, (self._master_sock))
|
self.transport.write(reg_packet, (self._master_sock))
|
||||||
logger.debug('->> (%s) Master Registration Request To:%s From:%s', self._network, self._master_sock, binascii.b2a_hex(self._local_id))
|
logger.debug('->> (%s) Master Registration Request To:%s From:%s', self._network, self._master_sock, binascii.b2a_hex(self._local_id))
|
||||||
|
|
||||||
elif (_master_connected == True):
|
elif (self._master_stat['CONNECTED'] == True):
|
||||||
master_alive_packet = hashed_packet(self._local['AUTH_KEY'], self.MASTER_ALIVE_PKT)
|
master_alive_packet = hashed_packet(self._local['AUTH_KEY'], self.MASTER_ALIVE_PKT)
|
||||||
self.transport.write(master_alive_packet, (self._master_sock))
|
self.transport.write(master_alive_packet, (self._master_sock))
|
||||||
logger.debug('->> (%s) Master Keep-alive %s Sent To:%s', self._network, self._master_stat['KEEP_ALIVES_SENT'], self._master_sock)
|
logger.debug('->> (%s) Master Keep-alive %s Sent To:%s', self._network, self._master_stat['KEEP_ALIVES_SENT'], self._master_sock)
|
||||||
@ -309,12 +326,12 @@ class IPSC(DatagramProtocol):
|
|||||||
else:
|
else:
|
||||||
logger.error('->> (%s) Master in UNKOWN STATE:%s:%s', self._network, self._master_sock)
|
logger.error('->> (%s) Master in UNKOWN STATE:%s:%s', self._network, self._master_sock)
|
||||||
|
|
||||||
if ((_master_connected == True) and (_peer_list_rx == False)):
|
if ((self._master_stat['CONNECTED'] == True) and (self._master_stat['PEER-LIST'] == False)):
|
||||||
peer_list_req_packet = hashed_packet(self._local['AUTH_KEY'], self.PEER_LIST_REQ_PKT)
|
peer_list_req_packet = hashed_packet(self._local['AUTH_KEY'], self.PEER_LIST_REQ_PKT)
|
||||||
self.transport.write(peer_list_req_packet, (self._master_sock))
|
self.transport.write(peer_list_req_packet, (self._master_sock))
|
||||||
logger.debug('->> (%s) List Reqested from Master:%s', self._network, self._master_sock)
|
logger.debug('->> (%s) List Reqested from Master:%s', self._network, self._master_sock)
|
||||||
|
|
||||||
if (_peer_list_rx == True):
|
if (self._master_stat['PEER-LIST'] == True):
|
||||||
for peer in (self._peers):
|
for peer in (self._peers):
|
||||||
if (peer['RADIO_ID'] == self._local_id): # We are in the peer-list, but don't need to talk to ourselves
|
if (peer['RADIO_ID'] == self._local_id): # We are in the peer-list, but don't need to talk to ourselves
|
||||||
continue
|
continue
|
||||||
@ -332,8 +349,8 @@ class IPSC(DatagramProtocol):
|
|||||||
|
|
||||||
if peer['STATUS']['KEEP_ALIVES_OUTSTANDING'] >= self._local['MAX_MISSED']:
|
if peer['STATUS']['KEEP_ALIVES_OUTSTANDING'] >= self._local['MAX_MISSED']:
|
||||||
peer['STATUS']['CONNECTED'] = False
|
peer['STATUS']['CONNECTED'] = False
|
||||||
self._peer_list.remove(peer['RADIO_ID'])
|
self._peer_list.remove(peer['RADIO_ID']) # Remove the peer from the simple list FIRST
|
||||||
self._peers.remove(peer)
|
self._peers.remove(peer) # Becuase once it's out of the dictionary, you can't use it for anything else.
|
||||||
logger.error('Maximum Peer Keep-Alives Missed -- De-registering the Peer: %s', peer)
|
logger.error('Maximum Peer Keep-Alives Missed -- De-registering the Peer: %s', peer)
|
||||||
|
|
||||||
peer['STATUS']['KEEP_ALIVES_SENT'] += 1
|
peer['STATUS']['KEEP_ALIVES_SENT'] += 1
|
||||||
@ -347,8 +364,7 @@ class IPSC(DatagramProtocol):
|
|||||||
# RECEIVED DATAGRAM - ACT IMMEDIATELY!!!
|
# RECEIVED DATAGRAM - ACT IMMEDIATELY!!!
|
||||||
#************************************************
|
#************************************************
|
||||||
|
|
||||||
# Work in progress -- at the very least, notify we have the packet. Ultimately
|
# Actions for recieved packets by type: Call a function or process here...
|
||||||
# call a function or process immediately if only a few actions
|
|
||||||
#
|
#
|
||||||
def datagramReceived(self, data, (host, port)):
|
def datagramReceived(self, data, (host, port)):
|
||||||
logger.debug('received %r from %s:%d', binascii.b2a_hex(data), host, port)
|
logger.debug('received %r from %s:%d', binascii.b2a_hex(data), host, port)
|
||||||
@ -357,17 +373,26 @@ class IPSC(DatagramProtocol):
|
|||||||
_peerid = data[1:5]
|
_peerid = data[1:5]
|
||||||
_dec_peerid = int(binascii.b2a_hex(_peerid), 16)
|
_dec_peerid = int(binascii.b2a_hex(_peerid), 16)
|
||||||
|
|
||||||
|
# First action: if Authentication is active, authenticate the packet
|
||||||
|
#
|
||||||
if bool(self._local['AUTH_KEY']) == True:
|
if bool(self._local['AUTH_KEY']) == True:
|
||||||
if validate_auth(self._local['AUTH_KEY'], data) == False:
|
if validate_auth(self._local['AUTH_KEY'], data) == False:
|
||||||
logger.warning('(%s) AuthError: IPSC packet failed authentication. Type %s: Peer ID: %s', self._network, binascii.b2a_hex(_packettype), _dec_peerid)
|
logger.warning('(%s) AuthError: IPSC packet failed authentication. Type %s: Peer ID: %s', self._network, binascii.b2a_hex(_packettype), _dec_peerid)
|
||||||
return
|
return
|
||||||
|
data = strip_hash(data)
|
||||||
|
|
||||||
|
# Packets generated by "users" that are the most common should come first for efficiency.
|
||||||
|
#
|
||||||
if (_packettype == GROUP_VOICE):
|
if (_packettype == GROUP_VOICE):
|
||||||
if not(valid_master(self._network, _peerid) == False or valid_peer(self._peer_list, _peerid) == False):
|
if not(valid_master(self._network, _peerid) == False or valid_peer(self._peer_list, _peerid) == False):
|
||||||
logger.warning('(%s) PeerError: Peer not in peer-list: %s', self._network, _dec_peerid)
|
logger.warning('(%s) PeerError: Peer not in peer-list: %s', self._network, _dec_peerid)
|
||||||
return
|
return
|
||||||
|
fwd_group_voice(self._network, data)
|
||||||
|
|
||||||
logger.debug('<<- (%s) Group Voice Packet From:%s:%s', self._network, host, port)
|
logger.debug('<<- (%s) Group Voice Packet From:%s:%s', self._network, host, port)
|
||||||
|
|
||||||
|
# IPSC keep alives, master and peer, come next in processing priority
|
||||||
|
#
|
||||||
elif (_packettype == PEER_ALIVE_REQ):
|
elif (_packettype == PEER_ALIVE_REQ):
|
||||||
if valid_peer(self._peer_list, _peerid) == False:
|
if valid_peer(self._peer_list, _peerid) == False:
|
||||||
|
|
||||||
@ -392,7 +417,10 @@ class IPSC(DatagramProtocol):
|
|||||||
for peer in self._config['PEERS']:
|
for peer in self._config['PEERS']:
|
||||||
if peer['RADIO_ID'] == _peerid:
|
if peer['RADIO_ID'] == _peerid:
|
||||||
peer['STATUS']['KEEP_ALIVES_OUTSTANDING'] = 0
|
peer['STATUS']['KEEP_ALIVES_OUTSTANDING'] = 0
|
||||||
|
|
||||||
|
# Registration requests and replies are infrequent, but important. Peer lists can go here too as a part
|
||||||
|
# of the registration process.
|
||||||
|
#
|
||||||
elif (_packettype == MASTER_REG_REQ):
|
elif (_packettype == MASTER_REG_REQ):
|
||||||
logger.debug('<<- (%s) Master Registration Packet Recieved', self._network)
|
logger.debug('<<- (%s) Master Registration Packet Recieved', self._network)
|
||||||
|
|
||||||
@ -414,13 +442,12 @@ class IPSC(DatagramProtocol):
|
|||||||
if peer['RADIO_ID'] == _peerid:
|
if peer['RADIO_ID'] == _peerid:
|
||||||
peer['STATUS']['CONNECTED'] = True
|
peer['STATUS']['CONNECTED'] = True
|
||||||
|
|
||||||
elif (_packettype == XCMP_XNL):
|
|
||||||
logger.debug('<<- (%s) XCMP_XNL From:%s:%s, but we did not indicate XCMP capable!', self._network, host, port)
|
|
||||||
|
|
||||||
elif (_packettype == PEER_LIST_REPLY):
|
elif (_packettype == PEER_LIST_REPLY):
|
||||||
logger.debug('<<- (%s) Peer List Received From:%s:%s', self._network, host, port)
|
logger.debug('<<- (%s) Peer List Received From:%s:%s', self._network, host, port)
|
||||||
self._peer_list = process_peer_list(data, self._network, self._peer_list)
|
self._peer_list = process_peer_list(data, self._network, self._peer_list)
|
||||||
|
|
||||||
|
# Other "user" related packet types that we don't do much or anything with yet
|
||||||
|
#
|
||||||
elif (_packettype == PVT_VOICE):
|
elif (_packettype == PVT_VOICE):
|
||||||
logger.debug('<<- (%s) Voice Packet From:%s:%s', self._network, host, port)
|
logger.debug('<<- (%s) Voice Packet From:%s:%s', self._network, host, port)
|
||||||
|
|
||||||
@ -430,18 +457,24 @@ class IPSC(DatagramProtocol):
|
|||||||
elif (_packettype == PVT_DATA):
|
elif (_packettype == PVT_DATA):
|
||||||
logger.debug('<<- (%s) Private Data Packet From From:%s:%s', self._network, host, port)
|
logger.debug('<<- (%s) Private Data Packet From From:%s:%s', self._network, host, port)
|
||||||
|
|
||||||
elif (_packettype == RPT_WAKE_UP):
|
|
||||||
logger.debug('<<- (%s) Repeater Wake-Up Packet From:%s:%s', self._network, host, port)
|
|
||||||
|
|
||||||
elif (_packettype == DE_REG_REQ):
|
elif (_packettype == DE_REG_REQ):
|
||||||
logger.debug('<<- (%s) Peer De-Registration Request From:%s:%s', self._network, host, port)
|
logger.debug('<<- (%s) Peer De-Registration Request From:%s:%s', self._network, host, port)
|
||||||
|
|
||||||
elif (_packettype == DE_REG_REPLY):
|
elif (_packettype == DE_REG_REPLY):
|
||||||
logger.debug('<<- (%s) Peer De-Registration Reply From:%s:%s', self._network, host, port)
|
logger.debug('<<- (%s) Peer De-Registration Reply From:%s:%s', self._network, host, port)
|
||||||
|
|
||||||
|
elif (_packettype == RPT_WAKE_UP):
|
||||||
|
logger.debug('<<- (%s) Repeater Wake-Up Packet From:%s:%s', self._network, host, port)
|
||||||
|
|
||||||
|
# Technically, we're not paying any attention to these types because we're not part of the XCMP call control structure
|
||||||
|
#
|
||||||
|
elif (_packettype == XCMP_XNL):
|
||||||
|
logger.debug('<<- (%s) XCMP_XNL From:%s:%s, but we did not indicate XCMP capable!', self._network, host, port)
|
||||||
|
|
||||||
elif (_packettype in (CALL_CTL_1, CALL_CTL_2, CALL_CTL_3)):
|
elif (_packettype in (CALL_CTL_1, CALL_CTL_2, CALL_CTL_3)):
|
||||||
logger.debug('<<- (%s) Call Control Packet From:%s:%s', self._network, host, port)
|
logger.debug('<<- (%s) Call Control Packet From:%s:%s', self._network, host, port)
|
||||||
|
|
||||||
|
# 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:
|
else:
|
||||||
packet_type = binascii.b2a_hex(_packettype)
|
packet_type = binascii.b2a_hex(_packettype)
|
||||||
logger.error('<<- (%s) Received Unprocessed Type %s From:%s:%s', self._network, packet_type, host, port)
|
logger.error('<<- (%s) Received Unprocessed Type %s From:%s:%s', self._network, packet_type, host, port)
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
# Configuration file for IPSC.py -- each network has several parts, some of this is muted by the script once it runs, thus there are placeholders
|
# Configuration file for IPSC.py -- each network has several parts, some of this is muted by the script once it runs, thus there are placeholders
|
||||||
NETWORK = {
|
NETWORK = {
|
||||||
'IPSC1': {
|
'IPSC1': {
|
||||||
|
'GROUP_VOICE': [
|
||||||
|
{'SRC_GROUP': b'\x00\x00\x01', 'DST_NET': 'IPSC2', 'DST_GROUP': b'\x00\x00\x02'}
|
||||||
|
],
|
||||||
'LOCAL': {
|
'LOCAL': {
|
||||||
'MODE': b'\x6A', # Decoded values below
|
'MODE': b'\x6A', # Decoded values below
|
||||||
'PEER_OPER': True,
|
'PEER_OPER': True,
|
||||||
|
Loading…
Reference in New Issue
Block a user