Updating packet types
This commit is contained in:
parent
1fc04b7acb
commit
f9a679ccc4
158
README.md
158
README.md
|
@ -30,14 +30,18 @@ The following sections of this document will include various packet types. This
|
||||||
GROUP_VOICE = 0x80 This is a group voice call
|
GROUP_VOICE = 0x80 This is a group voice call
|
||||||
GROUP_DATA = 0x83 This is a group data call
|
GROUP_DATA = 0x83 This is a group data call
|
||||||
PVT_DATA = 0x84 This is a private data call
|
PVT_DATA = 0x84 This is a private data call
|
||||||
REG_REQ = 0x90 Request registration with master
|
RPT_WAKE_UP = 0x85 Wakes up all repeaters on the IPSC
|
||||||
REG_REPLY = 0x91 Master registration request reply
|
MASTER_REG_REQ = 0x90 Request registration with master (from peer, to master)
|
||||||
|
MASTER_REG_REPLY = 0x91 Master registration request reply (from master, to peer)
|
||||||
PEER_LIST_REQ = 0x92 Request peer list from master
|
PEER_LIST_REQ = 0x92 Request peer list from master
|
||||||
PEER_LIST_REPLY = 0x93 Master peer list reply
|
PEER_LIST_REPLY = 0x93 Master peer list reply
|
||||||
PEER_KEEP_ALIVE_REQ = 0x94 Peer keep alive request
|
PEER_REG_REQ = 0x94 Peer registration request
|
||||||
PEER_KEEP_ALIVE_REPLY = 0x95 Peer keep alive response
|
PEER_REG_REPLY = 0x95 Peer registration response
|
||||||
KEEP_ALIVE_REQ = 0x96 Master keep alive request (to master)
|
MASTER_ALIVE_REQ = 0x96 Master keep alive request (to master)
|
||||||
KEEP_ALIVE_REPLY = 0x97 Master keep alive reply (from master)
|
MASTER_ALIVE_REPLY = 0x97 Master keep alive reply (from master)
|
||||||
|
PEER_ALIVE_REQ = 0x98 Peer keep alive request (to peer)
|
||||||
|
PEER_ALIVE_REPLY = 0x99 Peer keep alive reply (from peer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**AUTHENTICATION:**
|
**AUTHENTICATION:**
|
||||||
|
@ -63,7 +67,7 @@ The IPSC network truly "forms" when the first peer registers with the master. Al
|
||||||
|
|
||||||
* Master updates the peer list to all nodes when there is a change:
|
* Master updates the peer list to all nodes when there is a change:
|
||||||
MASTER -> (PEERS) (Master sends update list to each peer)
|
MASTER -> (PEERS) (Master sends update list to each peer)
|
||||||
PEERn -> NEW PEER (each peer 'n' sends keep alive requests to the new peer)
|
...all peers begin registration and then keep-alives
|
||||||
|
|
||||||
* ALL nodes continue sending/receiving keep alives to maintain the IPSC
|
* ALL nodes continue sending/receiving keep alives to maintain the IPSC
|
||||||
|
|
||||||
|
@ -146,143 +150,3 @@ Bytes 3-4 = 0x04, 0x00 = Oldest supported version? (same as above)
|
||||||
|
|
||||||
FULL_PAYLOAD = add_authentication(PAYLOAD, KEY)
|
FULL_PAYLOAD = add_authentication(PAYLOAD, KEY)
|
||||||
print(binascii.b2a_hex(FULL_PAYLOAD))
|
print(binascii.b2a_hex(FULL_PAYLOAD))
|
||||||
|
|
||||||
|
|
||||||
**Example Python3 code to register to a master, exchange keep alives, request, receive and decode the peer list:**
|
|
||||||
|
|
||||||
import socket
|
|
||||||
import binascii
|
|
||||||
import hmac
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
# 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')
|
|
||||||
},
|
|
||||||
'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'},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Known IPSC Message Types
|
|
||||||
RDAC_CTL = b'\x70'
|
|
||||||
GROUP_VOICE = b'\x80'
|
|
||||||
GROUP_DATA = b'\x83'
|
|
||||||
PVT_DATA = b'\x84'
|
|
||||||
REG_REQ = b'\x90'
|
|
||||||
REG_REPLY = b'\x91'
|
|
||||||
PEER_LIST_REQ = b'\x92'
|
|
||||||
PEER_LIST_REPLY = b'\x93'
|
|
||||||
PEER_KEEP_ALIVE_REQ = b'\x94'
|
|
||||||
PEER_KEEP_ALIVE_REPLY = b'\x95'
|
|
||||||
KEEP_ALIVE_REQ = b'\x96'
|
|
||||||
KEEP_ALIVE_REPLY = b'\x97'
|
|
||||||
|
|
||||||
# IPSC information
|
|
||||||
IPSC_TS_BOTH = b'\x6A' # Both Timeslots IPSC enabled
|
|
||||||
IPSC_OP_VER = b'\x04\x03' # 0x04, 0x03 -- seems to be current version of IPSC
|
|
||||||
IPSC_OLD_VER = b'\x04\x00' # 0x04, 0x02 -- oldest version of IPSC suppoerted
|
|
||||||
IPSC_FLAGS = b'\x00\x00\x80\xDC' # Just accept this... it works, we know some of the pieces
|
|
||||||
|
|
||||||
#********** FUNCTIONS THAT WE WILL USE
|
|
||||||
|
|
||||||
# function to send a payload to a defined socket
|
|
||||||
def send_auth_packet (_dest_addr, _dest_port, _socket, _data, _key):
|
|
||||||
_hash = binascii.unhexlify((hmac.new(_key,_data,hashlib.sha1)).hexdigest()[:20])
|
|
||||||
print("==> Sending Authenticated Packet")
|
|
||||||
print(" Destination IP:", _dest_addr)
|
|
||||||
print(" Destination UDP Port:", _dest_port)
|
|
||||||
print(" Raw Packet:", binascii.b2a_hex(_data + _hash))
|
|
||||||
_socket.sendto((_data+_hash), (_dest_addr, _dest_port))
|
|
||||||
return
|
|
||||||
|
|
||||||
# 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))
|
|
||||||
_mode = binascii.b2a_hex(_data[5:6])
|
|
||||||
print('<== Response Recieved from Radio ID:', _peer_id)
|
|
||||||
print(' Raw Packet:', binascii.b2a_hex(_data))
|
|
||||||
# Parse returned information
|
|
||||||
|
|
||||||
_packettype = (_data[0:1])
|
|
||||||
_sock = 'IPSC1'
|
|
||||||
|
|
||||||
if (_packettype == REG_REQ):
|
|
||||||
print(" >> This is a registration packet")
|
|
||||||
|
|
||||||
elif (_packettype == REG_REPLY):
|
|
||||||
print(" >> This is a registration reply packet")
|
|
||||||
|
|
||||||
elif (_packettype == PEER_LIST_REPLY):
|
|
||||||
print(">> This packet is a peer list from the master")
|
|
||||||
_num_peers = int(str(int(binascii.b2a_hex(_data[5:7]), 16))[1:])
|
|
||||||
# print('>>There are', binascii.b2a_hex(_data[5:7]), 'peers in this IPSC (RAW)')
|
|
||||||
print('>> There are', _num_peers, 'peers in this IPSC')
|
|
||||||
for i in range(7, (_num_peers*11)+7, 11):
|
|
||||||
NETWORK[_sock]['PEERS'].append({
|
|
||||||
'RADIO_ID': binascii.b2a_hex(_data[i:i+4]),
|
|
||||||
'IP': binascii.b2a_hex(_data[i+4:i+8]),
|
|
||||||
'PORT': binascii.b2a_hex(_data[i+8:i+10]),
|
|
||||||
'MODE': binascii.b2a_hex(_data[i+10:i+11])
|
|
||||||
})
|
|
||||||
print_peer_list('IPSC1')
|
|
||||||
|
|
||||||
return _data, _packettype
|
|
||||||
|
|
||||||
def print_peer_list(_ipsc_network):
|
|
||||||
print(NETWORK[_ipsc_network]['LOCAL']['DESCRIPTION'])
|
|
||||||
for dictionary in NETWORK[_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(address[0],".",address[1],".",address[2],".",address[3],"\t", sep='', end='')
|
|
||||||
print(port, radio_id, hex_mode, sep='\t')
|
|
||||||
return
|
|
||||||
|
|
||||||
#********** THE ACTUAL MEAT
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
ipsc1_sock.settimeout(60)
|
|
||||||
|
|
||||||
CTL_SUFFIX = (IPSC_TS_BOTH + IPSC_FLAGS + IPSC_OP_VER + IPSC_OLD_VER)
|
|
||||||
REG_REQ_PACKET = (REG_REQ + NETWORK['IPSC1']['LOCAL']['RADIO_ID'] + CTL_SUFFIX)
|
|
||||||
KEEP_ALIVE_PACKET = (KEEP_ALIVE_REQ + NETWORK['IPSC1']['LOCAL']['RADIO_ID'] + CTL_SUFFIX)
|
|
||||||
PEER_LIST_REQ_PACKET = (PEER_LIST_REQ + NETWORK['IPSC1']['LOCAL']['RADIO_ID'])
|
|
||||||
|
|
||||||
# Send registration packet
|
|
||||||
send_auth_packet(NETWORK['IPSC1']['MASTER']['IP'], NETWORK['IPSC1']['MASTER']['PORT'], ipsc1_sock, REG_REQ_PACKET, NETWORK['IPSC1']['LOCAL']['AUTH_KEY'])
|
|
||||||
receive_packet(ipsc1_sock)
|
|
||||||
|
|
||||||
# Send keep alive packet
|
|
||||||
send_auth_packet(NETWORK['IPSC1']['MASTER']['IP'], NETWORK['IPSC1']['MASTER']['PORT'], ipsc1_sock, KEEP_ALIVE_PACKET, NETWORK['IPSC1']['LOCAL']['AUTH_KEY'])
|
|
||||||
receive_packet(ipsc1_sock)
|
|
||||||
|
|
||||||
# Request peer list from master
|
|
||||||
send_auth_packet(NETWORK['IPSC1']['MASTER']['IP'], NETWORK['IPSC1']['MASTER']['PORT'], ipsc1_sock, PEER_LIST_REQ_PACKET, NETWORK['IPSC1']['LOCAL']['AUTH_KEY'])
|
|
||||||
receive_packet(ipsc1_sock)
|
|
||||||
|
|
||||||
ipsc1_sock.close
|
|
||||||
|
|
Loading…
Reference in New Issue