mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 17:33:54 +00:00
More refactoring and filling out
This commit is contained in:
parent
149186e07a
commit
8890668d11
@ -212,7 +212,7 @@ class ServerRaet(deeding.ParamDeed): # pylint: disable=W0232
|
||||
'''
|
||||
Set up server to transmit and recive on address
|
||||
'''
|
||||
connection.value = aiding.SocketNB(host=address.data.host, port=address.data.port)
|
||||
connection.value = aiding.SocketUdpNb(host=address.data.host, port=address.data.port)
|
||||
connection.value.reopen() # create socket connection
|
||||
host, port = connection.value.ha
|
||||
address.update(host=host, port=port, ha=(host, port))
|
||||
|
@ -17,106 +17,110 @@ except ImportError:
|
||||
from ioflo.base.odicting import odict
|
||||
from ioflo.base.aiding import packByte, unpackByte
|
||||
|
||||
from salt.transport import table
|
||||
from . import raeting
|
||||
|
||||
class Stack(object):
|
||||
''' RAET protocol stack object'''
|
||||
def __init__(self):
|
||||
''' Setup Stack instance'''
|
||||
self.devices = odict() #devices managed by this stack
|
||||
|
||||
class Device(object):
|
||||
''' RAET protocol endpoint device object'''
|
||||
def __init__(self, did=0, stack=None, host='', port=raeting.RAET_PORT):
|
||||
''' Setup Device instance'''
|
||||
self.did = did # device id
|
||||
self.stack = stack # Stack object that manages this device
|
||||
self.host = socket.gethostbyname(host)
|
||||
self.port = port
|
||||
|
||||
@property
|
||||
def ha(self):
|
||||
'''ha property that returns ip address (host, port) tuple'''
|
||||
return (self.host, self.port)
|
||||
from . import stacking
|
||||
|
||||
class Part(object):
|
||||
'''
|
||||
Base class for parts of a RAET packet
|
||||
Should be subclassed
|
||||
'''
|
||||
def __init__(self, packet=None, kind=None, length=None, **kwa):
|
||||
''' Setup Part instance '''
|
||||
def __init__(self, packet=None, kind=None, **kwa):
|
||||
'''
|
||||
Setup Part instance
|
||||
'''
|
||||
self.packet = packet # Packet this Part belongs too
|
||||
self.kind = kind # part kind
|
||||
self.length = length # specified length of part not computed length
|
||||
self.packed = ''
|
||||
|
||||
def __len__(self):
|
||||
''' Return the size property '''
|
||||
return self.size
|
||||
'''
|
||||
Returns the length of .packed
|
||||
'''
|
||||
return len(self.packed)
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
''' size property returns the length of the .packed of this Part'''
|
||||
return len(self.packed)
|
||||
'''
|
||||
Property is the length of this Part
|
||||
'''
|
||||
return self.__len__()
|
||||
|
||||
class Head(Part):
|
||||
'''
|
||||
RAET protocol packet header object
|
||||
RAET protocol packet header class
|
||||
Manages the header portion of a packet
|
||||
'''
|
||||
def __init__(self, **kwa):
|
||||
''' Setup Head instance'''
|
||||
'''
|
||||
Setup Head instance
|
||||
'''
|
||||
super(Head, self).__init__(**kwa)
|
||||
self.data = odict(raeting.HEAD_DEFAULTS) #ensures correct order
|
||||
|
||||
class TxHead(Head):
|
||||
'''
|
||||
RAET protocl transmit packet header class
|
||||
'''
|
||||
|
||||
def pack(self):
|
||||
''' Composes and returns .packed, which is the packed form of this part '''
|
||||
'''
|
||||
Composes and returns .packed, which is the packed form of this part
|
||||
'''
|
||||
self.packed = ''
|
||||
self.data = odict(raeting.HEAD_DEFAULTS) # refresh
|
||||
self.data['vn'] = self.packet.version
|
||||
self.data['pk'] = self.packet.kind
|
||||
self.kind= self.packet.data['hk']
|
||||
data = self.packet.data # for speed
|
||||
|
||||
self.data['cf'] = self.packet.crdrFlag
|
||||
self.data['mf'] = self.packet.multFlag
|
||||
self.data['bf'] = self.packet.brstFlag
|
||||
self.data['pf'] = self.packet.pendFlag
|
||||
self.data['af'] = self.packet.allFlag
|
||||
data['pk'] = self.packet.kind
|
||||
data['nk'] = self.packet.neck.kind
|
||||
data['nl'] = self.packet.neck.size
|
||||
data['bk'] = self.packet.body.kind
|
||||
data['bl'] = self.packet.body.size
|
||||
data['tk'] = self.packet.tail.kind
|
||||
data['tl'] = self.packet.tail.size
|
||||
|
||||
self.data['nk'] = self.packet.neck.kind
|
||||
self.data['nl'] = self.packet.neck.size
|
||||
self.data['bk'] = self.packet.body.kind
|
||||
self.data['bl'] = self.packet.body.size
|
||||
self.data['tk'] = self.packet.tail.kind
|
||||
self.data['tl'] = self.packet.tail.size
|
||||
|
||||
self.data['fg'] = "{:02x}".format(self.packFlags())
|
||||
data['fg'] = "{:02x}".format(self.packFlags())
|
||||
|
||||
# kit always includes header kind and length fields
|
||||
kit = odict([('hk', self.kind), ('hl', 0)])
|
||||
for k, v in raeting.HEAD_DEFAULTS.items():# include if not equal to default
|
||||
if (self.data[k] != v) and (k not in raeting.PACKET_FLAGS ):
|
||||
kit[k] = self.data[k]
|
||||
for k, v in raeting.PACKET_DEFAULTS.items():# include if not equal to default
|
||||
if ( (k in raeting.HEAD_FIELDS) and
|
||||
(k not in raeting.PACKET_FLAGS ) and
|
||||
(data[k] != v)):
|
||||
kit[k] = data[k]
|
||||
|
||||
if self.kind == raeting.headKinds.json:
|
||||
kit['hl'] = '00' # need hex string so fixed length and jsonable
|
||||
packed = json.dumps(kit, separators=(',', ':'), encoding='ascii',)
|
||||
packed = '{0}{1}'.format(packed, raeting.JSON_END)
|
||||
self.length = len(packed)
|
||||
if self.length > raeting.MAX_HEAD_LEN:
|
||||
hl = len(packed)
|
||||
if hl > raeting.MAX_HEAD_LEN:
|
||||
self.packet.error = "Head length of {0}, exceeds max of {1}".format(hl, MAX_HEAD_LEN)
|
||||
return self.packed
|
||||
#subsitute true length converted to 2 byte hex string
|
||||
self.packed = packed.replace('"hl":"00"', '"hl":"{0}"'.format("{0:02x}".format(self.length)[-2:]), 1)
|
||||
self.packed = packed.replace('"hl":"00"', '"hl":"{0}"'.format("{0:02x}".format(hl)[-2:]), 1)
|
||||
|
||||
return self.packed
|
||||
|
||||
def packFlags(self):
|
||||
'''
|
||||
Packs all the flag fields into a single two char hex string
|
||||
'''
|
||||
values = []
|
||||
for field in raeting.PACKET_FLAG_FIELDS:
|
||||
values.append(1 if self.data.get(field, 0) else 0)
|
||||
return packByte(format='11111111', fields=values)
|
||||
|
||||
class RxHead(Head):
|
||||
'''
|
||||
RAET protocl receive packet header class
|
||||
'''
|
||||
|
||||
def parse(self, rest):
|
||||
'''
|
||||
Parses and removes head from packed rest and returns remainder
|
||||
'''
|
||||
self.packed = ''
|
||||
self.data = odict(raeting.HEAD_DEFAULTS) # refresh
|
||||
if rest.startswith('{"hk":1,') and raeting.JSON_END in rest: # json header
|
||||
self.kind = raeting.headKinds.json
|
||||
front, sep, back = rest.partition(raeting.JSON_END)
|
||||
@ -133,8 +137,8 @@ class Head(Part):
|
||||
self.packet.error = 'Recognized head kind does not match head field value.'
|
||||
return rest
|
||||
|
||||
self.length = int(self.data['hl'], 16)
|
||||
if self.length != self.size:
|
||||
hl = int(self.data['hl'], 16)
|
||||
if hl != self.size:
|
||||
self.packet.error = 'Actual head length does not match head field value.'
|
||||
|
||||
else: # notify unrecognizible packet head
|
||||
@ -143,41 +147,59 @@ class Head(Part):
|
||||
|
||||
return rest
|
||||
|
||||
def packFlags(self):
|
||||
''' Packs all the flag fields into a single two char hex string '''
|
||||
values = []
|
||||
for field in raeting.PACKET_FLAG_FIELDS:
|
||||
values.append(1 if self.data.get(field, 0) else 0)
|
||||
return packByte(format='11111111', fields=values)
|
||||
|
||||
def unpackFlags(self, flags):
|
||||
''' Unpacks all the flag fields from a single two char hex string '''
|
||||
'''
|
||||
Unpacks all the flag fields from a single two char hex string
|
||||
'''
|
||||
values = unpackByte(format='11111111', byte=int(flags, 16), boolean=False)
|
||||
for i, field in enumerate(raeting.PACKET_FLAG_FIELDS):
|
||||
if field in self.data:
|
||||
self.data[field] = values[i]
|
||||
|
||||
|
||||
|
||||
|
||||
class Neck(Part):
|
||||
'''
|
||||
RAET protocol packet neck object
|
||||
RAET protocol packet neck class
|
||||
Manages the signing or authentication of the packet
|
||||
'''
|
||||
def __init__(self, **kwa):
|
||||
''' Setup Neck instance'''
|
||||
'''
|
||||
Setup Neck instance
|
||||
'''
|
||||
super(Neck, self).__init__(**kwa)
|
||||
|
||||
class TxNeck(Neck):
|
||||
'''
|
||||
RAET protocol transmit packet neck class
|
||||
'''
|
||||
|
||||
def pack(self):
|
||||
''' Composes and returns .packed, which is the packed form of this part '''
|
||||
'''
|
||||
Composes and returns .packed, which is the packed form of this part
|
||||
'''
|
||||
self.packed = ''
|
||||
if self.kind == raeting.neckKinds.nada:
|
||||
self.kind= self.packet.data['nk']
|
||||
|
||||
if self.kind not in raeting.NECK_KIND_NAMES:
|
||||
self.kind = raeting.neckKinds.unknown
|
||||
self.packet.error = "Unrecognizible packet neck."
|
||||
return self.packed
|
||||
|
||||
if self.kind == raeting.neckKinds.nacl:
|
||||
self.packed = "".rjust(raeting.neckSizes.nacl, '\x00')
|
||||
|
||||
elif self.kind == raeting.neckKinds.nada:
|
||||
pass
|
||||
|
||||
return self.packed
|
||||
|
||||
class RxNeck(Neck):
|
||||
'''
|
||||
RAET protocol receive packet neck class
|
||||
'''
|
||||
def parse(self, rest):
|
||||
''' Parses and removes neck from rest and returns rest '''
|
||||
'''
|
||||
Parses and removes neck from rest and returns rest
|
||||
'''
|
||||
self.packed = ''
|
||||
self.kind = self.packet.head.data['nk']
|
||||
|
||||
@ -186,9 +208,9 @@ class Neck(Part):
|
||||
self.packet.error = "Unrecognizible packet neck."
|
||||
return rest
|
||||
|
||||
self.length = self.packet.head.data['nl']
|
||||
self.packed = rest[:self.length]
|
||||
rest = rest[self.length:]
|
||||
nl = self.packet.head.data['nl']
|
||||
self.packed = rest[:nl]
|
||||
rest = rest[nl:]
|
||||
|
||||
if self.kind == raeting.neckKinds.nada:
|
||||
pass
|
||||
@ -196,23 +218,39 @@ class Neck(Part):
|
||||
|
||||
class Body(Part):
|
||||
'''
|
||||
RAET protocol packet body object
|
||||
RAET protocol packet body class
|
||||
Manages the messsage portion of the packet
|
||||
'''
|
||||
def __init__(self, data=None, **kwa):
|
||||
''' Setup Body instance'''
|
||||
'''
|
||||
Setup Body instance
|
||||
'''
|
||||
super(Body, self).__init__(**kwa)
|
||||
self.data = data or odict()
|
||||
|
||||
class TxBody(Body):
|
||||
'''
|
||||
RAET protocol tx packet body class
|
||||
'''
|
||||
def pack(self):
|
||||
''' Composes and returns .packed, which is the packed form of this part'''
|
||||
'''
|
||||
Composes and returns .packed, which is the packed form of this part
|
||||
'''
|
||||
self.packed = ''
|
||||
self.kind= self.packet.data['bk']
|
||||
if self.kind == raeting.bodyKinds.json:
|
||||
self.packed = json.dumps(self.data, separators=(',', ':'))
|
||||
return self.packed
|
||||
|
||||
class RxBody(Body):
|
||||
'''
|
||||
RAET protocol rx packet body class
|
||||
'''
|
||||
|
||||
def parse(self, rest):
|
||||
''' Parses and removes head from rest and returns rest '''
|
||||
'''
|
||||
Parses and removes head from rest and returns rest
|
||||
'''
|
||||
self.packed = ''
|
||||
self.kind = self.packet.head.data['bk']
|
||||
|
||||
@ -221,13 +259,13 @@ class Body(Part):
|
||||
self.packet.error = "Unrecognizible packet body."
|
||||
return rest
|
||||
|
||||
self.length = self.packet.head.data['bl']
|
||||
self.packed = rest[:self.length]
|
||||
rest = rest[self.length:]
|
||||
bl = self.packet.head.data['bl']
|
||||
self.packed = rest[:bl]
|
||||
rest = rest[bl:]
|
||||
self.data = odict()
|
||||
|
||||
if self.kind == raeting.bodyKinds.json:
|
||||
if self.length:
|
||||
if bl:
|
||||
kit = json.loads(self.packed, object_pairs_hook=odict)
|
||||
if not isinstance(kit, Mapping):
|
||||
self.packet.error = "Packet body not a mapping."
|
||||
@ -241,24 +279,37 @@ class Body(Part):
|
||||
|
||||
class Tail(Part):
|
||||
'''
|
||||
RAET protocol packet tail object
|
||||
Manages the verification of the body portion of the packet
|
||||
RAET protocol packet tail class
|
||||
Supports encrypt/decrypt or other validation of body portion of packet
|
||||
'''
|
||||
def __init__(self, **kwa):
|
||||
''' Setup Tail instal'''
|
||||
super(Tail, self).__init__(**kwa)
|
||||
|
||||
class TxTail(Tail):
|
||||
'''
|
||||
RAET protocol tx packet tail class
|
||||
'''
|
||||
|
||||
def pack(self):
|
||||
'''
|
||||
Composes and returns .packed, which is the packed form of this part
|
||||
'''
|
||||
self.packed = ''
|
||||
self.kind= self.packet.data['tk']
|
||||
if self.kind == raeting.tailKinds.nada:
|
||||
pass
|
||||
return self.packed
|
||||
|
||||
class RxTail(Tail):
|
||||
'''
|
||||
RAET protocol rx packet tail class
|
||||
'''
|
||||
|
||||
def parse(self, rest):
|
||||
''' Parses and removes tail from rest and returns rest '''
|
||||
'''
|
||||
Parses and removes tail from rest and returns rest
|
||||
'''
|
||||
self.packed = ''
|
||||
self.kind = self.packet.head.data['tk']
|
||||
|
||||
@ -267,9 +318,9 @@ class Tail(Part):
|
||||
self.packet.error = "Unrecognizible packet tail."
|
||||
return rest
|
||||
|
||||
self.length = self.packet.head.data['tl']
|
||||
self.packed = rest[:self.length]
|
||||
rest = rest[self.length:]
|
||||
tl = self.packet.head.data['tl']
|
||||
self.packed = rest[:tl]
|
||||
rest = rest[tl:]
|
||||
|
||||
if self.kind == raeting.tailKinds.nada:
|
||||
pass
|
||||
@ -277,70 +328,109 @@ class Tail(Part):
|
||||
return rest
|
||||
|
||||
class Packet(object):
|
||||
''' RAET protocol packet object '''
|
||||
def __init__(self, stack=None, version=None, kind=None,
|
||||
sh='', sp=raeting.RAET_PORT,
|
||||
dh='127.0.0.1', dp=raeting.RAET_PORT,
|
||||
body=None, data=None, raw=None):
|
||||
'''
|
||||
RAET protocol packet object
|
||||
'''
|
||||
def __init__(self, stack=None, kind=None, local=None, remote=None):
|
||||
''' Setup Packet instance. Meta data for a packet. '''
|
||||
self.stack = stack # stack that handles this packet
|
||||
self.version = version or raeting.HEAD_DEFAULTS['vn']
|
||||
self.kind = kind or raeting.HEAD_DEFAULTS['pk']
|
||||
self.src = Device(host=sh, port=sp) # source device
|
||||
self.dst = Device(host=dh, port=dp) # destination device
|
||||
self.head = Head(packet=self)
|
||||
self.neck = Neck(packet=self)
|
||||
self.body = Body(packet=self, data=body)
|
||||
self.tail = Tail(packet=self)
|
||||
self.kind = kind or raeting.PACKET_DEFAULTS['pk']
|
||||
if not local and self.stack:
|
||||
local = self.stack.device
|
||||
self.local = local or stacking.LocalDevice(stack=self.stack) # source device
|
||||
self.remote = remote or stacking.RemoteDevice(stack=self.stack) # destination device
|
||||
self.packed = '' #packed string
|
||||
self.error = ''
|
||||
if data:
|
||||
self.load(data)
|
||||
if raw:
|
||||
self.parse(raw)
|
||||
self.data = odict(raeting.PACKET_DEFAULTS)
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
''' size property returns the length of the .packed of this Packet'''
|
||||
'''
|
||||
Property is the length of the .packed of this Packet
|
||||
'''
|
||||
return len(self.packed)
|
||||
|
||||
def load(self, data=None):
|
||||
''' Loud up attributes of parts if provided '''
|
||||
data = data or odict()
|
||||
raeting.updateMissing(data, raeting.PACKET_DEFAULTS)
|
||||
self.version = data['vn']
|
||||
self.crdrFlag = data['cf']
|
||||
self.multFlag = data['mf']
|
||||
self.brstFlag = data['bf']
|
||||
self.pendFlag = data['pf']
|
||||
self.allFlag = data['af']
|
||||
|
||||
self.src.did = data['sd']
|
||||
self.src.host = data['sh']
|
||||
self.src.port = data['sp']
|
||||
self.dst.did = data['dd']
|
||||
self.dst.host = data['dh']
|
||||
self.dst.port = data['dp']
|
||||
self.head.kind=data['hk']
|
||||
self.neck.kind=data['nk']
|
||||
self.body.kind=data['bk']
|
||||
self.tail.kind=data['tk']
|
||||
def refresh(self, data=None):
|
||||
'''
|
||||
Refresh .data to defaults and update if data
|
||||
'''
|
||||
self.data = odict(raeting.PACKET_DEFAULTS)
|
||||
if data:
|
||||
self.data.update(data)
|
||||
return self # so can method chain
|
||||
|
||||
class TxPacket(Packet):
|
||||
'''
|
||||
RAET Protocol Transmit Packet object
|
||||
'''
|
||||
def __init__(self, embody=None, data=None, **kwa):
|
||||
'''
|
||||
Setup TxPacket instance
|
||||
'''
|
||||
super(TxPacket, self).__init__(**kwa)
|
||||
self.head = TxHead(packet=self)
|
||||
self.neck = TxNeck(packet=self)
|
||||
self.body = TxBody(packet=self, data=embody)
|
||||
self.tail = TxTail(packet=self)
|
||||
if data:
|
||||
self.data.update(data)
|
||||
if embody and data:
|
||||
self.pack()
|
||||
|
||||
def pack(self):
|
||||
''' pack the parts of the packet and then the full packet'''
|
||||
'''
|
||||
Pack the parts of the packet and then the full packet
|
||||
'''
|
||||
self.error = ''
|
||||
self.body.pack()
|
||||
self.tail.pack()
|
||||
self.head.pack()
|
||||
self.neck.pack()
|
||||
self.head.pack()
|
||||
self.packed = '{0}{1}{2}{3}'.format(self.head.packed, self.neck.packed, self.body.packed, self.tail.packed)
|
||||
self.sign()
|
||||
return self.packed
|
||||
|
||||
def sign(self):
|
||||
'''
|
||||
Sign .packed using neck
|
||||
'''
|
||||
return True
|
||||
|
||||
|
||||
class RxPacket(Packet):
|
||||
'''
|
||||
RAET Protocol Receive Packet object
|
||||
'''
|
||||
def __init__(self, raw=None, **kwa):
|
||||
'''
|
||||
Setup RxPacket instance
|
||||
'''
|
||||
super(RxPacket, self).__init__(**kwa)
|
||||
self.head = RxHead(packet=self)
|
||||
self.neck = RxNeck(packet=self)
|
||||
self.body = RxBody(packet=self)
|
||||
self.tail = RxTail(packet=self)
|
||||
if raw:
|
||||
self.parse(raw)
|
||||
|
||||
def parse(self, raw):
|
||||
''' Parses raw packet '''
|
||||
'''
|
||||
Parses raw packet
|
||||
'''
|
||||
self.error = ''
|
||||
rest = self.head.parse(raw)
|
||||
|
||||
if self.head.data['vn'] not in raeting.VERSIONS.values():
|
||||
self.error = ("Received incompatible version '{0}'"
|
||||
"version '{1}'".format(self.head.data['vn']))
|
||||
return
|
||||
#self.version = self.head.data['vn']
|
||||
self.crdrFlag = self.head.data['cf']
|
||||
self.bcstFlag = self.head.data['bf']
|
||||
self.scdtFlag = self.head.data['sf']
|
||||
self.pendFlag = self.head.data['pf']
|
||||
self.allFlag = self.head.data['af']
|
||||
|
||||
rest = self.neck.parse(rest)
|
||||
if not self.vouch():
|
||||
return
|
||||
@ -351,14 +441,15 @@ class Packet(object):
|
||||
|
||||
return rest
|
||||
|
||||
def vouch(self):
|
||||
''' Uses signature in neck to vouch for (authenticate) packet '''
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def verify(self):
|
||||
''' Uses tail to verify body does not have errors '''
|
||||
|
||||
'''
|
||||
Uses signature in neck to verify (authenticate) packet
|
||||
'''
|
||||
return True
|
||||
|
||||
|
||||
def validate(self):
|
||||
'''
|
||||
Uses tail to validate body
|
||||
'''
|
||||
return True
|
@ -39,14 +39,14 @@ header data =
|
||||
sd: Source Device ID (SDID)
|
||||
dd: Destination Device ID (DDID)
|
||||
cf: Corresponder Flag (CrdrFlag) Default 0
|
||||
mf: Multicast Flag (MultFlag) Default 0
|
||||
bf: BroadCast Flag (BcstFlag) Default 0
|
||||
|
||||
si: Session ID (SID) Default 0
|
||||
ti: Transaction ID (TID) Default 0
|
||||
sk: Service Kind (SrvcKind)
|
||||
pk: Packet Kind (PcktKind)
|
||||
bf: Burst Flag (BrstFlag) Default 0
|
||||
Send segments or ordered packets without waiting for interleaved acks
|
||||
sf: Succedent Flag (ScdtFlag) Default 0
|
||||
Send segments or ordered packets without waiting for interleafed acks
|
||||
|
||||
oi: order index (OrdrIndx) Default 0
|
||||
dt: Datetime Stamp (Datetime) Default 0
|
||||
@ -69,7 +69,7 @@ header data =
|
||||
tl: tail length (TailLen) Default 0
|
||||
|
||||
fg: flags packed (Flags) Default '00' hs
|
||||
2 char Hex string with bits (0, 0, af, pf, 0, bf, mf, cf)
|
||||
2 char Hex string with bits (0, 0, af, pf, 0, sf, bf, cf)
|
||||
Zeros are TBD flags
|
||||
}
|
||||
|
||||
@ -108,14 +108,16 @@ headKinds = HeadKind(**HEAD_KINDS) # headKinds.json is '00'
|
||||
VERSIONS = odict([('0.1', 0)])
|
||||
VERSION_NAMES = odict((v, k) for k, v in VERSIONS.iteritems())
|
||||
|
||||
NECK_KINDS = odict([('nada', 0), ('sodium', 1), ('sha2', 2),
|
||||
VERSION = VERSIONS.values()[0]
|
||||
|
||||
NECK_KINDS = odict([('nada', 0), ('nacl', 1), ('sha2', 2),
|
||||
('crc64', 2), ('unknown', 255)])
|
||||
NECK_KIND_NAMES = odict((v, k) for k, v in NECK_KINDS.iteritems()) # inverse map
|
||||
NeckKind = namedtuple('NeckKind', NECK_KINDS.keys())
|
||||
neckKinds = NeckKind(**NECK_KINDS)
|
||||
|
||||
# bytes
|
||||
NECK_SIZES = odict([('nada', 0), ('sodium', 0), ('sha2', 0),
|
||||
NECK_SIZES = odict([('nada', 0), ('nacl', 64), ('sha2', 0),
|
||||
('crc64', 8), ('unknown', 0)])
|
||||
NeckSize = namedtuple('NeckSize', NECK_SIZES.keys())
|
||||
neckSizes = NeckSize(**NECK_SIZES)
|
||||
@ -131,7 +133,8 @@ TailKind = namedtuple('TailKind', TAIL_KINDS.keys())
|
||||
tailKinds = TailKind(**TAIL_KINDS)
|
||||
|
||||
# bytes
|
||||
TAIL_SIZES = odict([('nada', 0), ('crc16', 2), ('crc64', 8), ('unknown', 0)])
|
||||
TAIL_SIZES = odict([('nada', 0), ('nacl', 16), ('crc16', 2), ('crc64', 8),
|
||||
('unknown', 0)])
|
||||
TailSize = namedtuple('TailSize', TAIL_SIZES.keys())
|
||||
tailSizes = TailSize(**TAIL_SIZES)
|
||||
|
||||
@ -149,44 +152,49 @@ packetKinds = PacketKind(**PACKET_KINDS)
|
||||
|
||||
|
||||
# head fields that may be included in json header if not default value
|
||||
HEAD_DEFAULTS = odict([
|
||||
('hk', 0),
|
||||
('hl', 0),
|
||||
('vn', 0),
|
||||
('sd', 0),
|
||||
('dd', 0),
|
||||
('cf', 0),
|
||||
('mf', 0),
|
||||
('si', 0),
|
||||
('ti', 0),
|
||||
('sk', 0),
|
||||
('pk', 0),
|
||||
('bf', 0),
|
||||
('oi', 0),
|
||||
('dt', 0),
|
||||
('sn', 0),
|
||||
('sc', 1),
|
||||
('pf', 0),
|
||||
('af', 0),
|
||||
('nk', 0),
|
||||
('nl', 0),
|
||||
('bk', 0),
|
||||
('bl', 0),
|
||||
('tk', 0),
|
||||
('tl', 0),
|
||||
('fg', '00'),
|
||||
])
|
||||
|
||||
PACKET_DEFAULTS = odict([
|
||||
('sh', ''),
|
||||
('sp', 7530),
|
||||
('dh', '127.0.0.1'),
|
||||
('dp', 7530),
|
||||
])
|
||||
PACKET_DEFAULTS.update(HEAD_DEFAULTS)
|
||||
('hk', 0),
|
||||
('hl', 0),
|
||||
('vn', 0),
|
||||
('sd', 0),
|
||||
('dd', 0),
|
||||
('cf', 0),
|
||||
('bf', 0),
|
||||
('si', 0),
|
||||
('ti', 0),
|
||||
('sk', 0),
|
||||
('pk', 0),
|
||||
('sf', 0),
|
||||
('oi', 0),
|
||||
('dt', 0),
|
||||
('sn', 0),
|
||||
('sc', 1),
|
||||
('pf', 0),
|
||||
('af', 0),
|
||||
('nk', 0),
|
||||
('nl', 0),
|
||||
('bk', 0),
|
||||
('bl', 0),
|
||||
('tk', 0),
|
||||
('tl', 0),
|
||||
('fg', '00'),
|
||||
])
|
||||
|
||||
PACKET_FLAGS = ['af', 'pf', 'bf', 'mf', 'cf']
|
||||
PACKET_FLAG_FIELDS = ['', '', 'af', 'pf', '', 'bf', 'mf', 'cf']
|
||||
PACKET_FIELDS = [ 'sh', 'sp', 'dh', 'dp',
|
||||
'hk', 'hl', 'vn', 'sd', 'dd', 'cf', 'bf', 'si', 'ti', 'sk', 'pk',
|
||||
'sf', 'oi', 'dt', 'sn', 'sc', 'pf', 'af',
|
||||
'nk', 'nl', 'bk', 'bl', 'tk', 'tl', 'fg']
|
||||
|
||||
HEAD_FIELDS = [ 'hk', 'hl', 'vn', 'sd', 'dd', 'cf', 'bf', 'si', 'ti', 'sk', 'pk',
|
||||
'sf', 'oi', 'dt', 'sn', 'sc', 'pf', 'af',
|
||||
'nk', 'nl', 'bk', 'bl','tk', 'tl', 'fg']
|
||||
|
||||
PACKET_FLAGS = ['af', 'pf', 'sf', 'bf', 'cf']
|
||||
PACKET_FLAG_FIELDS = ['', '', 'af', 'pf', '', 'sf', 'bf', 'cf']
|
||||
|
||||
|
||||
def defaultData(data=None):
|
||||
|
@ -4,8 +4,8 @@ stacking.py raet protocol stacking classes
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
from collections import deque
|
||||
|
||||
import socket
|
||||
from collections import deque, namedtuple, Mapping
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
@ -13,11 +13,184 @@ except ImportError:
|
||||
|
||||
# Import ioflo libs
|
||||
from ioflo.base.odicting import odict
|
||||
from ioflo.base.globaling import *
|
||||
|
||||
from ioflo.base import aiding
|
||||
from ioflo.base import storing
|
||||
from ioflo.base import deeding
|
||||
|
||||
from salt.transport.table.public import pynacl
|
||||
|
||||
from . import raeting
|
||||
from . import nacling
|
||||
|
||||
from ioflo.base.consoling import getConsole
|
||||
console = getConsole()
|
||||
|
||||
|
||||
class Stack(object):
|
||||
'''
|
||||
RAET protocol stack object
|
||||
'''
|
||||
def __init__( self,
|
||||
version=raeting.VERSION,
|
||||
device=None, ha=("", raeting.RAET_PORT)):
|
||||
'''
|
||||
Setup Stack instance
|
||||
'''
|
||||
self.version = version
|
||||
# local device for this stack
|
||||
self.device = device or Device(stack=self, ha=ha)
|
||||
# remote devices attached to this stack
|
||||
self.devices = odict()
|
||||
self.transactions = odict() #transactions
|
||||
|
||||
self.serverUdp = aiding.SocketUdpNb(ha=self.device.ha)
|
||||
self.serverUdp.reopen() # open socket
|
||||
|
||||
class Device(object):
|
||||
'''
|
||||
RAET protocol endpoint device object
|
||||
'''
|
||||
Did = 0 # class attribute
|
||||
|
||||
def __init__( self, stack=None, did=None, sid=0, tid=0,
|
||||
host="", port=raeting.RAET_PORT, ha=None, ):
|
||||
'''
|
||||
Setup Device instance
|
||||
'''
|
||||
self.stack = stack # Stack object that manages this device
|
||||
if did is None:
|
||||
did = Device.Did
|
||||
Device.Did += 1
|
||||
self.did = did # device ID
|
||||
|
||||
self.sid = sid # current session ID
|
||||
self.tid = tid # current transaction ID
|
||||
|
||||
if ha: #takes precendence
|
||||
host, port = ha
|
||||
self.host = socket.gethostbyname(host)
|
||||
self.port = port
|
||||
|
||||
@property
|
||||
def ha(self):
|
||||
'''
|
||||
property that returns ip address (host, port) tuple
|
||||
'''
|
||||
return (self.host, self.port)
|
||||
|
||||
def nextSid(self):
|
||||
'''
|
||||
Generates next session id number.
|
||||
'''
|
||||
self.sid += 1
|
||||
if (self.sid > 0xffffffffL):
|
||||
self.sid = 1 # rollover to 1
|
||||
return self.sid
|
||||
|
||||
def nextTid(self):
|
||||
'''
|
||||
Generates next session id number.
|
||||
'''
|
||||
self.tid += 1
|
||||
if (self.tid > 0xffffffffL):
|
||||
self.tid = 1 # rollover to 1
|
||||
return self.tid
|
||||
|
||||
class LocalDevice(Device):
|
||||
'''
|
||||
RAET protocol endpoint local device object
|
||||
Maintains signer for signing and privateer for encrypt/decript
|
||||
'''
|
||||
def __init__(self, signkey=None, prikey=None, **kwa):
|
||||
'''
|
||||
Setup Device instance
|
||||
|
||||
signkey is either nacl SigningKey or hex encoded key
|
||||
prikey is either nacl PrivateKey or hex encoded key
|
||||
'''
|
||||
super(LocalDevice, self).__init__(**kwa)
|
||||
self.signer = nacling.Signer(signkey)
|
||||
self.privateer = nacling.Privateer(key)
|
||||
|
||||
class RemoteDevice(Device):
|
||||
'''
|
||||
RAET protocol endpoint remote device object
|
||||
Maintains verifier for verifying signatures and publican for encrypt/decript
|
||||
'''
|
||||
def __init__(self, verikey=None, pubkey=None, **kwa):
|
||||
'''
|
||||
Setup Device instance
|
||||
|
||||
verikey is either nacl VerifyKey or hex encoded key
|
||||
pubkey is either nacl PublicKey or hex encoded key
|
||||
'''
|
||||
if 'host' not in kwa and 'ha' not in kwa:
|
||||
kwa['ha'] = ('127.0.0.1', raeting.RAET_PORT)
|
||||
super(LocalDevice, self).__init__(**kwa)
|
||||
self.verifier = nacling.Verifier(verikey)
|
||||
self.publican = nacling.Publican(pubkey)
|
||||
|
||||
class Transaction(object):
|
||||
'''
|
||||
RAET protocol transaction class
|
||||
'''
|
||||
def __init__(self, stack=None, kind=None, sdid=None, ddid=None,
|
||||
crdr=None, bcst=False, sid=None, tid=None, ):
|
||||
'''
|
||||
Setup Transaction instance
|
||||
'''
|
||||
self.stack = stack
|
||||
self.kind = kind or raeting.PACKET_DEFAULTS['sk']
|
||||
self.sdid = sdid
|
||||
self.ddid = ddid
|
||||
self.crdr = crdr
|
||||
self.bcst = bcst
|
||||
self.sid = sid
|
||||
self.tid = tid
|
||||
|
||||
def start(self):
|
||||
return None # next packet or None
|
||||
|
||||
|
||||
class Initiator(Transaction):
|
||||
'''
|
||||
RAET protocol initiator transaction class
|
||||
'''
|
||||
def __init__(self, sdid=None, crdr=False, **kwa):
|
||||
'''
|
||||
Setup Transaction instance
|
||||
'''
|
||||
if sdid is None:
|
||||
sdid = self.stack.device.did
|
||||
crdr = False # force crdr to False
|
||||
super(Initiator, self).__init__(sdid, crdr, **kwa)
|
||||
|
||||
|
||||
class Corresponder(Transaction):
|
||||
'''
|
||||
RAET protocol corresponder transaction class
|
||||
'''
|
||||
def __init__(self, ddid=None, crdr=True, **kwa):
|
||||
'''
|
||||
Setup Transaction instance
|
||||
'''
|
||||
if ddid is None:
|
||||
ddid = self.stack.device.did
|
||||
crdr = True # force crdr to True
|
||||
super(Corresponder, self).__init__(ddid, crdr, **kwa)
|
||||
|
||||
class Join(Initiator):
|
||||
'''
|
||||
RAET protocol Join transaction class
|
||||
'''
|
||||
def __init__(self, ddid=None, **kwa):
|
||||
'''
|
||||
Setup Transaction instance
|
||||
'''
|
||||
if ddid is None:
|
||||
ddid = self.stack.devices.values()[0].did # first is channel master
|
||||
super(Initiator, self).__init__(ddid, **kwa)
|
||||
|
||||
def start(self)
|
||||
'''
|
||||
Build first packet
|
||||
'''
|
||||
return None
|
@ -185,6 +185,12 @@ class Public(object):
|
||||
'''
|
||||
return self._key.sign(msg)
|
||||
|
||||
def signature(self, msg):
|
||||
'''
|
||||
Return only the signature string resulting from signing the message
|
||||
'''
|
||||
return self._key.signature(msg)
|
||||
|
||||
def verify(self, signed):
|
||||
'''
|
||||
Verify that the signed message is valid
|
||||
|
@ -135,6 +135,15 @@ class Key(object):
|
||||
sig = self.sign_key.sign(hash_)
|
||||
return sig + msg
|
||||
|
||||
def signature(self, msg):
|
||||
'''
|
||||
Return only signature string resulting from signing the msg
|
||||
'''
|
||||
hash_ = Crypto.Hash.SHA.new()
|
||||
hash_.update(msg)
|
||||
sig = self.sign_key.sign(hash_)
|
||||
return sig
|
||||
|
||||
def verify(self, msg):
|
||||
'''
|
||||
Verify a message
|
||||
|
@ -104,6 +104,12 @@ class Key(object):
|
||||
'''
|
||||
return self.sign_key.sign(msg)
|
||||
|
||||
def signature(self, msg):
|
||||
'''
|
||||
Return only the signature string resulting from signing the message
|
||||
'''
|
||||
return self.sign(msg).signature
|
||||
|
||||
def verify(self, msg):
|
||||
'''
|
||||
Verify the message
|
||||
|
@ -4,20 +4,31 @@ Tests to try out table. Potentially ephemeral
|
||||
|
||||
'''
|
||||
|
||||
import json
|
||||
|
||||
from salt.transport import table
|
||||
|
||||
def test_table():
|
||||
bob_pub = table.Public()
|
||||
print bob_pub.backend
|
||||
print bob_pub.sec_backend
|
||||
print bob_pub.keydata
|
||||
print bob_pub.public
|
||||
print bob_pub.secret
|
||||
|
||||
|
||||
print json.dumps(bob_pub.keydata, indent=2)
|
||||
|
||||
#print bob_pub.backend
|
||||
#print bob_pub.sec_backend
|
||||
#print bob_pub.public
|
||||
#print bob_pub.secret
|
||||
|
||||
signed = bob_pub.sign("What have we here.")
|
||||
print type(signed)
|
||||
print len(signed.message)
|
||||
print len(signed.signature)
|
||||
print type(signed.signature)
|
||||
print signed.message
|
||||
print signed.signature
|
||||
print signed
|
||||
|
||||
signature = bob_pub.signature("What have we here.")
|
||||
print signature
|
||||
print signature == signed.signature
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
Reference in New Issue
Block a user