Merge pull request #2 from adamfast/master

Python logging module, generic configuration loader.
This commit is contained in:
Cort Buffington 2013-06-29 13:07:00 -07:00
commit 1fc04b7acb
4 changed files with 220 additions and 169 deletions

10
.gitignore vendored
View File

@ -1,11 +1,5 @@
.DS_Store
.dropbox
<<<<<<< HEAD
<<<<<<< HEAD
Icon
=======
Icon
>>>>>>> b8ce998cf4206fbbba382f94e0224bacd4713389
=======
Icon
>>>>>>> b8ce998cf4206fbbba382f94e0224bacd4713389
my_ipsc_config.py
*.pyc

View File

@ -10,18 +10,18 @@ This work represents the author's interpretation of the Motorola(tm) MOTOTRBO(tm
This document assumes the reader is familiar with the concepts presented in the Motorola Solutions(tm), Inc. MOTOTRBO(tm) Systems Planner.
**CONVENTIONS USED:**
When communications exchanges are described, the symbols "->" and "<-" are used to donote the *direction* of the communcation. For example, "PEER -> MASTER" indicates communcation from the peer to the master. For each exchange outlined, the initiator of the particular communcation will be on the left for the duration of the particular item being illustrated.
When communications exchanges are described, the symbols "->" and "<-" are used to denote the *direction* of the communcation. For example, "PEER -> MASTER" indicates communcation from the peer to the master. For each exchange outlined, the initiator of the particular communication will be on the left for the duration of the particular item being illustrated.
###CONNECTION ESTABLISHMENT AND MAINTENANCE
**CORE CONCEPTS:**
The IPSC system contains, essentially, two types of nodes: Master and Peer. Each IPSC network has exactly one master device and zero or more peers, recommended not to exceed 15. IPSC nodes may be a number of types of systems, such as repeaters, dispatch consoles, application software, etc. For example, the Motorola RDAC applicaiton acts as a peer in the IPSC network, though it doesn't operate as a repeater. The IPSC protocol supports many possible node types, and only a few have been identified. This document currently only explores repeaters - both Master and Peer, and their roles in the IPSC network.
The IPSC system contains, essentially, two types of nodes: Master and Peer. Each IPSC network has exactly one master device and zero or more peers, recommended not to exceed 15. IPSC nodes may be a number of types of systems, such as repeaters, dispatch consoles, application software, etc. For example, the Motorola RDAC application acts as a peer in the IPSC network, though it doesn't operate as a repeater. The IPSC protocol supports many possible node types, and only a few have been identified. This document currently only explores repeaters - both Master and Peer, and their roles in the IPSC network.
All IPSC communication is via UDP, and only the master needs a static IP address. Masters will operate behind NATs. A single UDP port, specified in programming the IPSC master device must be mapped thorugh any NAT/stateful firewalls for the master, while peers require no special treatment.
All IPSC communication is via UDP, and only the master needs a static IP address. Masters will operate behind NATs. A single UDP port, specified in programming the IPSC master device must be mapped through any NAT/stateful firewalls for the master, while peers require no special treatment.
All nodes in an IPSC network maintain communication with each other at all times. The role of the master is merely to coordinate the joining of new nodes to the IPSC network. A functional IPSC network will continue without its master, as long as no new nodes need to join (or existing nodes need to re-join after a communications outage, etc.) This is one of the most important core concepts in IPSC, as it is central to the NAT traversal AND tracking of active peers.
Each peer will send keep-alives to each other peer in the IPSC network at an interval specified in the devices "firewall open timer". The elegantly simple, yet effective approach of IPSC, uses this keep-alive to both open, and keep open stateful firewall and NAT translations between peers. Since each device handles all communications from a single UDP port, when a device sends a keep-alive or a registration request to another device, the source-destination address/port tuple for that commonication is opened through stateful devices. The only requirement to maintain communication is that this timer be shorter than the UDP session timeout of network control elements (firewalls, packet shapers, NATs, etc.) Moreover, it does NOT appear that all devices in the IPSC require the same setting for this. Each device would appear to maintain its own set timing without interference from different interval settings on other nodes in the IPSC.
Each peer will send keep-alives to each other peer in the IPSC network at an interval specified in the devices "firewall open timer". The elegantly simple, yet effective approach of IPSC, uses this keep-alive to both open, and keep open stateful firewall and NAT translations between peers. Since each device handles all communications from a single UDP port, when a device sends a keep-alive or a registration request to another device, the source-destination address/port tuple for that communication is opened through stateful devices. The only requirement to maintain communication is that this timer be shorter than the UDP session timeout of network control elements (firewalls, packet shapers, NATs, etc.) Moreover, it does NOT appear that all devices in the IPSC network require the same setting for this. Each device would appear to maintain its own set timing without interference from different interval settings on other nodes in the IPSC.
**KNOWN IPSC PACKET TYPES:**
The following sections of this document will include various packet types. This is a list of currently known types and their meanings. Note: The names are arbitrarily chosen with the intention of being descriptive, and each is defined by what they've been "observed" to do in the wild.
@ -34,14 +34,14 @@ The following sections of this document will include various packet types. This
REG_REPLY = 0x91 Master registration request reply
PEER_LIST_REQ = 0x92 Request peer list from master
PEER_LIST_REPLY = 0x93 Master peer list reply
PEER_KEEP_ALIVE_REQ = 0x94 Peer keep alive request
PEER_KEEP_ALIVE_REPLY = 0x95 Peer keep alive response
KEEP_ALIVE_REQ = 0x96 Master keep alive request (to maseter)
PEER_KEEP_ALIVE_REQ = 0x94 Peer keep alive request
PEER_KEEP_ALIVE_REPLY = 0x95 Peer keep alive response
KEEP_ALIVE_REQ = 0x96 Master keep alive request (to master)
KEEP_ALIVE_REPLY = 0x97 Master keep alive reply (from master)
**AUTHENTICATION:**
Most IPSC netowrks will be operated as "authenticated". This means that a key is used to create a digest of the packets exchanged in order to authenticate them. Each node in the IPSC network must have the authentication key programmed in order for the mechanism to work. The process is based on the SHA-1 digest protocol, where the "key" is a 20 byte hexadecimal *string* (if a shorter key is programmed, leading zeros are used to create a 20 byte key). The IPSC payload and the key are used to create the digest, of which only the most significant 10 bytes are used (the last 10 are truncated). This digest is appended to the end of the IPSC payload before transmission. An example is illustrated below:
Most IPSC networks will be operated as "authenticated". This means that a key is used to create a digest of the packets exchanged in order to authenticate them. Each node in the IPSC network must have the authentication key programmed in order for the mechanism to work. The process is based on the SHA-1 digest protocol, where the "key" is a 20 byte hexadecimal *string* (if a shorter key is programmed, leading zeros are used to create a 20 byte key). The IPSC payload and the key are used to create the digest, of which only the most significant 10 bytes are used (the last 10 are truncated). This digest is appended to the end of the IPSC payload before transmission. An example is illustrated below:
IPSC Registration Packet Digest
90000000016a000080dc04030400 b0ec45f4c3f8fb0c0b1d
@ -82,7 +82,7 @@ PEER LIST REQUEST:
PEER LIST RESPONSE:
TYPE(1 Byte) + SRC_ID (4 Bytes) + NUM_PEERS* (2 Bytes) + {PEER_ID, PEER_IP, PEER_PORT, PEER_LINKING}... [+ AUTHENTICATION (10 Bytes)]
TYPE(1 Byte) + SRC_ID (4 Bytes) + NUM_PEERS * (2 Bytes) + {PEER_ID, PEER_IP, PEER_PORT, PEER_LINKING}... [+ AUTHENTICATION (10 Bytes)]
93 0004c2c0 002c*
00000001 6ccf7505 c351 6a
0004c2c3 d17271e9 c35a 6a
@ -124,13 +124,13 @@ NUMBER of PEERS: 2 Bytes
Byte 5 - 0x00 = Unknown
Byte 6 - Number of Peers (not including us)
Protocol VERSION: 4 Bytes (These are pure guesses based on repaeter and c-Bridge code revisions)
Protocol VERSION: 4 Bytes (These are pure guesses based on repeater and c-Bridge code revisions)
Bytes 1-2 - 0x04, 0x03 = Current version? (numbering scheme unknown)
Bytes 3-4 = 0x04, 0x00 = Oldest supported version? (same as above)
**SAMPLE CODE:**
*Sample Python3 code to genearate the authentication digest:*
*Sample Python3 code to generate the authentication digest:*
import binascii
import hmac
@ -148,7 +148,7 @@ Bytes 3-4 = 0x04, 0x00 = Oldest supported version? (same as above)
print(binascii.b2a_hex(FULL_PAYLOAD))
**Example Python3 code to register to a master, exchange keep alives, reqest, recieve and decode the peer list:**
**Example Python3 code to register to a master, exchange keep alives, request, receive and decode the peer list:**
import socket
import binascii
@ -158,22 +158,23 @@ Bytes 3-4 = 0x04, 0x00 = Oldest supported version? (same as above)
# Data structure for holding IPSC information
NETWORK = {
'IPSC1': {
'LOCAL': {
'DESCRIPTION': 'K0USY Lecompton, KS - Master',
'MODE': b'\x6A',
'PORT': 50001,
'RADIO_ID': binascii.unhexlify('00000001'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000012345')
},
'MASTER': {
'IP': '24.143.49.121',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50001,
'RADIO_ID': binascii.unhexlify('00000001'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000000001')
},
'MASTER': {
'IP': '1.1.1.1',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
}
}
@ -209,7 +210,7 @@ Bytes 3-4 = 0x04, 0x00 = Oldest supported version? (same as above)
_socket.sendto((_data+_hash), (_dest_addr, _dest_port))
return
# Note: This function ignores authentiation information!!!
# Note: This function ignores authentication information!!!
def receive_packet(_socket):
_data = (_socket.recv(1024))
_peer_id = str(int(binascii.b2a_hex(_data[2:5]), 16))
@ -261,7 +262,7 @@ Bytes 3-4 = 0x04, 0x00 = Oldest supported version? (same as above)
#********** THE ACTUAL MEAT
# Create a socket to conetact IPSC Network #1
# Create a socket to contact IPSC Network #1
ipsc1_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ipsc1_sock.bind(('', NETWORK['IPSC1']['LOCAL']['PORT']))
ipsc1_sock.setblocking(0)

317
ipsc.py
View File

@ -6,87 +6,143 @@ import argparse
import binascii
import hmac
import hashlib
import logging
from logging.config import dictConfig
dictConfig({
'version': 1,
'disable_existing_loggers': False,
'filters': {
},
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'timed': {
'format': '%(levelname)s %(asctime)s %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'formatter': 'simple',
'filename': '/tmp/ipsc.log',
},
'console-timed': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'timed'
},
'file-timed': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'formatter': 'timed',
'filename': '/tmp/ipsc.log',
},
},
'loggers': {
'ipsc': {
# 'handlers': ['file-timed', 'console-timed'],
'handlers': ['file', 'console'],
'level': 'DEBUG',
'propagate': True,
}
}
})
logger = logging.getLogger('ipsc')
# Data structure for holding IPSC information
NETWORK = {
'IPSC1': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50001,
'RADIO_ID': binascii.unhexlify('00000001'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000000001')
try:
from my_ipsc_config import NETWORK
except ImportError:
NETWORK = {
'IPSC1': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50001,
'RADIO_ID': binascii.unhexlify('00000001'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000000001')
},
'MASTER': {
'IP': '1.1.1.1',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
},
'MASTER': {
'IP': '1.1.1.1',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
'IPSC2': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50002,
'RADIO_ID': binascii.unhexlify('00000002'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000000022')
},
'MASTER': {
'IP': '2.2.2.2',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
},
'IPSC2': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50002,
'RADIO_ID': binascii.unhexlify('00000002'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000000022')
'IPSC3': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50003,
'RADIO_ID': binascii.unhexlify('00000003'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000000333')
},
'MASTER': {
'IP': '3.3.3.3',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
},
'MASTER': {
'IP': '2.2.2.2',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
},
'IPSC3': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50003,
'RADIO_ID': binascii.unhexlify('00000003'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000000333')
},
'MASTER': {
'IP': '3.3.3.3',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
},
'IPSC4': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50004,
'RADIO_ID': binascii.unhexlify('00000004'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000004444')
},
'MASTER': {
'IP': '4.4.4.4',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
'IPSC4': {
'LOCAL': {
'DESCRIPTION': 'IPSC Network #1',
'MODE': b'\x6A',
'FLAGS': b'\x00\x00\x80\xDC',
'PORT': 50004,
'RADIO_ID': binascii.unhexlify('00000004'),
'AUTH_KEY': binascii.unhexlify('0000000000000000000000000000000000004444')
},
'MASTER': {
'IP': '4.4.4.4',
'MODE': b'\x6A',
'PORT': 50000,
'RADIO_ID': '',
},
'PEERS': [ # each list entry will be a dictionary for IP, RADIO ID and PORT
#{'IP': '100.200.1.1', 'PORT': 50000, 'RADIO_ID': b'\x00\x00\x00\xFF'},
]
}
}
}
# Known IPSC Message Types
@ -115,23 +171,23 @@ IPSC_VER = IPSC_OP_VER + IPSC_OLD_VER
def hashed_packet(key, data):
hash = binascii.unhexlify((hmac.new(key,data,hashlib.sha1)).hexdigest()[:20])
return (data + hash)
def print_peer_list(_ipsc_network):
print('\t', _ipsc_network['LOCAL']['DESCRIPTION'])
for dictionary in _ipsc_network['PEERS']:
hex_address = dictionary['IP']
hex_port = dictionary['PORT']
hex_radio_id = dictionary['RADIO_ID']
hex_mode = dictionary['MODE']
address = [int(hex_address[0:2], 16), int(hex_address[2:4], 16), int(hex_address[4:6], 16), int(hex_address[6:8], 16)]
port = int(hex_port, 16)
radio_id = int(hex_radio_id, 16)
print ('\t', address[0],address[1],address[2],address[3], sep='.', end='\t')
print (port, radio_id, sep=':', end=' ')
print ("IPSC Mode:", hex_mode)
print()
logger.info('\t%s', _ipsc_network['LOCAL']['DESCRIPTION'])
for dictionary in _ipsc_network['PEERS']:
hex_address = dictionary['IP']
hex_port = dictionary['PORT']
hex_radio_id = dictionary['RADIO_ID']
hex_mode = dictionary['MODE']
address = [int(hex_address[0:2], 16), int(hex_address[2:4], 16), int(hex_address[4:6], 16), int(hex_address[6:8], 16)]
port = int(hex_port, 16)
radio_id = int(hex_radio_id, 16)
logger.info('\t%s.%s.%s.%s\t', address[0], address[1], address[2], address[3])
logger.info('%s:%s ', port, radio_id)
logger.info("IPSC Mode: %s", hex_mode)
logger.info("")
class IPSC(DatagramProtocol):
@ -147,21 +203,20 @@ class IPSC(DatagramProtocol):
self.PEER_ALIVE_REQ_PKT = (PEER_ALIVE_REQ + self._config['LOCAL']['RADIO_ID'] + self.TS_FLAGS)
self.PEER_ALIVE_REPLY_PKT = (PEER_ALIVE_REPLY + self._config['LOCAL']['RADIO_ID'] + self.TS_FLAGS)
else:
print("Unexpected arguments found.")
logger.error("Unexpected arguments found.")
def masterKeepalive(self):
master_alive_packet = hashed_packet(self._config['LOCAL']['AUTH_KEY'], self.MASTER_ALIVE_PKT)
self.transport.write(master_alive_packet, (self._config['MASTER']['IP'], self._config['MASTER']['PORT']))
print("->> Master Keep Alive Sent To:\t", self._config['MASTER']['IP'],":", self._config['MASTER']['PORT'], "\n")
logger.info("->> Master Keep Alive Sent To:\t%s:%s\n", self._config['MASTER']['IP'], self._config['MASTER']['PORT'])
def startProtocol(self):
print ("*** config: %s" % self._config)
print ()
print ("*** Starting up IPSC Client and Registering to the Master ***")
logger.debug("*** config: %s", self._config)
logger.info("")
logger.info("*** Starting up IPSC Client and Registering to the Master ***")
reg_packet = hashed_packet(self._config['LOCAL']['AUTH_KEY'], self.MASTER_REG_REQ_PKT)
self.transport.write(reg_packet, (self._config['MASTER']['IP'], self._config['MASTER']['PORT']))
print ("->> Sending Registration to Master:\t", self._config['MASTER']['IP'],":", self._config['MASTER']['PORT'],
"\tFrom:", binascii.b2a_hex(self._config['LOCAL']['RADIO_ID']), "\n")
logger.info("->> Sending Registration to Master:\t%s:%s\tFrom:%s\n", self._config['MASTER']['IP'], self._config['MASTER']['PORT'], binascii.b2a_hex(self._config['LOCAL']['RADIO_ID']))
#
self._call = task.LoopingCall(self.masterKeepalive)
self._loop = self._call.start(6)
@ -169,55 +224,55 @@ class IPSC(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
dest_ip = self._config['MASTER']['IP']
dest_port = self._config['MASTER']['PORT']
#print "received %r from %s:%d" % (binascii.b2a_hex(data), host, port)
#logger.info("received %r from %s:%d", binascii.b2a_hex(data), host, port)
_packettype = (data[0:1])
if (_packettype == MASTER_REG_REQ):
print("<<- Registration Packet Recieved\n")
logger.info("<<- Registration Packet Recieved\n")
elif (_packettype == MASTER_REG_REPLY):
print("<<- Master Registration Reply From:\t", host,":",port)
logger.info("<<- Master Registration Reply From:\t%s:%s", host, port)
master_alive_packet = hashed_packet(self._config['LOCAL']['AUTH_KEY'], self.MASTER_ALIVE_PKT)
self.transport.write(master_alive_packet, (host, port))
print("->> Master Keep Alive Sent To:\t", host,":",port, "\n")
logger.info("->> Master Keep Alive Sent To:\t%s:%s\n", host, port)
# the only time we need to ask for the peer list is after we've registered to the master
peer_list_req_packet = hashed_packet(self._config['LOCAL']['AUTH_KEY'], self.PEER_LIST_REQ_PKT)
self.transport.write(peer_list_req_packet, (host, port))
print("->> Peer List Reqested from Master:\t", host,":",port, "\n")
#print binascii.b2a_hex(peer_list_req_packet)
logger.info("->> Peer List Reqested from Master:\t%s:%s\n", host, port)
#logger.info(binascii.b2a_hex(peer_list_req_packet))
elif (_packettype == PEER_REG_REQUEST):
print("<<- Peer Registration Request From:\t", host,":",port)
logger.info("<<- Peer Registration Request From:\t%s:%s", host, port)
peer_reg_reply_packet = hashed_packet(self._config['LOCAL']['AUTH_KEY'], self.PEER_REG_REPLY_PKT)
self.transport.write(peer_reg_reply_packet, (host, port))
print("->> Peer Registration Reply Sent To:\t", host,":",port,"\n")
#print host, port
#print binascii.b2a_hex(peer_reg_reply_packet)
logger.info("->> Peer Registration Reply Sent To:\t%s:%s\n", host, port)
#logger.info("%s:%s", host, port)
#logger.info(binascii.b2a_hex(peer_reg_reply_packet))
elif (_packettype == PEER_ALIVE_REQ):
print("<<- Received Peer Keep Alive From:\t", host,":",port)
logger.info("<<- Received Peer Keep Alive From:\t%s:%s", host, port)
peer_alive_req_packet = hashed_packet(self._config['LOCAL']['AUTH_KEY'], self.PEER_ALIVE_REQ_PKT)
peer_alive_reply_packet = hashed_packet(self._config['LOCAL']['AUTH_KEY'], self.PEER_ALIVE_REPLY_PKT)
self.transport.write(peer_alive_reply_packet, (host, port))
print("->> Sent Peer Keep Alive Reply To:\t\t", host,":",port,)
logger.info("->> Sent Peer Keep Alive Reply To:\t\t%s:%s", host, port)
self.transport.write(peer_alive_req_packet, (host, port))
print("->> Sent Peer Keep Alive Request To:\t\t", host,":",port, "\n")
#print binascii.b2a_hex(peer_alive_req_packet)
logger.info("->> Sent Peer Keep Alive Request To:\t\t%s:%s\n", host, port)
#logger.info(binascii.b2a_hex(peer_alive_req_packet))
elif (_packettype == MASTER_ALIVE_REPLY):
print("<<- Keep Alive Recieved from Master:\t", host,":",port, "\n")
logger.info("<<- Keep Alive Received from Master:\t%s:%s\n", host, port)
elif (_packettype == PEER_ALIVE_REPLY):
print("<<- Keep Alive Recieved from Peer:\t", host,":",port, "\n")
logger.info("<<- Keep Alive Received from Peer:\t%s:%s\n", host, port)
elif (_packettype == RDAC_CTL):
print("<<- RDAC and/or Control Packet From:\t", host,":",port, "\n")
logger.info("<<- RDAC and/or Control Packet From:\t%s:%s\n", host, port)
elif (_packettype == PEER_LIST_REPLY):
print("<<- The Peer List has been Received from Master:\t", host,":",port)
logger.info("<<- The Peer List has been Received from Master:\t%s:%s", host, port)
_num_peers = int(str(int(binascii.b2a_hex(data[5:7]), 16))[1:])
print(' There are', _num_peers, 'peers in this IPSC Network')
logger.info(' There are %s peers in this IPSC Network', _num_peers)
for i in range(7, (_num_peers*11)+7, 11):
self._config['PEERS'].append({
'RADIO_ID': binascii.b2a_hex(data[i:i+4]),
@ -226,11 +281,11 @@ class IPSC(DatagramProtocol):
'MODE': binascii.b2a_hex(data[i+10:i+11])
})
print_peer_list(self._config)
print()
logger.info("")
else:
packet_type = binascii.b2a_hex(_packettype)
print("<<- Recieved Unprocessed Type", packet_type, "From:\t", host,":",port,"\n")
logger.error("<<- Received Unprocessed Type %s From:\t%s:%s\n", packet_type, host, port)
if __name__ == '__main__':
@ -240,14 +295,14 @@ if __name__ == '__main__':
if args.network is not None:
if args.network in NETWORK:
print("Connecting to %s" % args.network)
logger.info("Connecting to %s", args.network)
reactor.listenUDP(NETWORK[args.network]['LOCAL']['PORT'], IPSC(NETWORK[args.network]))
else:
print("%s is not a configured ISPC network." % args.network)
logger.info("%s is not a configured ISPC network.", args.network)
exit()
else: # connect to all
print("No network supplied, connecting to all networks.")
logger.info("No network supplied, connecting to all networks.")
for ipsc_network in NETWORK:
reactor.listenUDP(NETWORK[ipsc_network]['LOCAL']['PORT'], IPSC(NETWORK[ipsc_network]))

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
Twisted==13.0.0