Some refactoring of segmentation

This commit is contained in:
Samuel M Smith 2014-02-21 17:41:10 -07:00
parent af885336d3
commit b52edc89da
4 changed files with 172 additions and 84 deletions

View File

@ -111,12 +111,12 @@ 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, rsid=0, rtid=0, **kwa):
def __init__(self, verkey=None, pubkey=None, rsid=0, rtid=0, **kwa):
'''
Setup Device instance
verikey is either nacl VerifyKey or hex encoded key
pubkey is either nacl PublicKey or hex encoded key
verkey is either nacl VerifyKey or raw or hex encoded key
pubkey is either nacl PublicKey or raw or hex encoded key
'''
if 'host' not in kwa and 'ha' not in kwa:
kwa['ha'] = ('127.0.0.1', raeting.RAET_TEST_PORT)
@ -125,7 +125,7 @@ class RemoteDevice(Device):
self.allowed = None
self.privee = nacling.Privateer() # short term key manager
self.publee = nacling.Publican() # correspondent short term key manager
self.verfer = nacling.Verifier(verikey) # correspondent verify key manager
self.verfer = nacling.Verifier(verkey) # correspondent verify key manager
self.pubber = nacling.Publican(pubkey) # correspondent long term key manager
self.rsid = rsid # last sid received from remote when RmtFlag is True

View File

@ -65,15 +65,14 @@ class TxHead(Head):
'''
self.packed = ''
data = self.packet.data # for speed
if not self.packet.segmentive: #only set these if packet is not a segment
data['bl'] = self.packet.body.size
data['cl'] = self.packet.coat.size
#if not self.packet.segmentive: #only set these if packet is not a segment
#data['bl'] = self.packet.body.size
#data['cl'] = self.packet.coat.size
data['fl'] = self.packet.foot.size
data['fg'] = "{:02x}".format(self.packFlags())
# kit always includes header kind and length fields
kit = odict([('hk', data['hk']), ('hl', 0)])
kit = odict([('ri', 'RAET'), ('pl', 0), ('hl', 0)])
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
@ -81,17 +80,25 @@ class TxHead(Head):
kit[k] = data[k]
if data['hk'] == raeting.headKinds.json:
kit['pl'] = '0000000' # need hex string so fixed length and jsonable
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)
hl = len(packed)
if hl > raeting.MAX_HEAD_LEN:
emsg = "Head length of {0}, exceeds max of {1}".format(hl, MAX_HEAD_LEN)
if hl > raeting.MAX_HEAD_SIZE:
emsg = "Head length of {0}, exceeds max of {1}".format(hl, MAX_HEAD_SIZE)
raise raeting.PacketError(emsg)
data['hl'] = hl
pl = hl + self.packet.coat.size + data['fl']
if pl > raeting.MAX_PACKET_SIZE:
emsg = "Packet length of {0}, exceeds max of {1}".format(hl, MAX_PACKET_SIZE)
raise raeting.PacketError(emsg)
data['pl'] = pl
#subsitute true length converted to 2 byte hex string
packed = packed.replace('"pl":"0000000"', '"pl":"{0}"'.format("{0:07x}".format(pl)[-7:]), 1)
self.packed = packed.replace('"hl":"00"', '"hl":"{0}"'.format("{0:02x}".format(hl)[-2:]), 1)
def packFlags(self):
'''
Packs all the flag fields into a single two char hex string
@ -114,7 +121,7 @@ class RxHead(Head):
self.packed = ''
data = self.packet.data # for speed
packed = self.packet.packed # for speed
if packed.startswith('{"hk":1,') and raeting.JSON_END in packed: # json header
if packed.startswith('{"ri":"RAET",') and raeting.JSON_END in packed: # json header
hk = raeting.headKinds.json
front, sep, back = packed.partition(raeting.JSON_END)
self.packed = "{0}{1}".format(front, sep)
@ -134,6 +141,11 @@ class RxHead(Head):
emsg = 'Actual head length does not match head field value.'
raise raeting.PacketError(emsg)
data['hl'] = hl
pl = int(data['pl'], 16)
#if pl != self.packet.size:
#emsg = 'Actual packet length does not match head field value.'
#raise raeting.PacketError(emsg)
data['pl'] = pl
else: # notify unrecognizible packet head
data['hk'] = raeting.headKinds.unknown
@ -196,10 +208,10 @@ class RxBody(Body):
emsg = "Unrecognizible packet body."
raise raeting.PacketError(emsg)
if self.size != self.packet.data['bl']:
emsg = ("Mismatching body size '{0}' and data length '{1}'"
"".format(self.size, self.packet.data['bl']))
raise raeting.PacketError(emsg)
#if self.size != self.packet.data['bl']:
#emsg = ("Mismatching body size '{0}' and data length '{1}'"
#"".format(self.size, self.packet.data['bl']))
#raise raeting.PacketError(emsg)
self.data = odict()
@ -244,8 +256,7 @@ class TxCoat(Coat):
self.packed = "".join([cipher, nonce])
if ck == raeting.coatKinds.nada:
#self.packed = self.packet.body.packed
pass
self.packed = self.packet.body.packed
class RxCoat(Coat):
'''
@ -273,7 +284,7 @@ class RxCoat(Coat):
self.packet.body.packed = self.packed
if ck == raeting.coatKinds.nada:
#self.packet.body.packed = self.packed
self.packet.body.packed = self.packed
pass
class Foot(Part):
@ -409,9 +420,10 @@ class Packet(object):
@property
def segmentive(self):
'''
Property is True if packet segment count is > 1
Property is True
If packet segment flag is True Or packet segment count is > 1
'''
return (True if self.data.get('sc', 1) > 1 else False)
return (True if (self.data.get('sf') or (self.data.get('sc', 1) > 1)) else False)
def refresh(self, data=None):
'''
@ -456,7 +468,7 @@ class TxPacket(Packet):
'''
self.foot.sign()
self.packed = ''.join([self.head.packed,
self.coat.packed or self.body.packed,
self.coat.packed,
self.foot.packed])
def encrypt(self, msg):
@ -476,7 +488,7 @@ class TxPacket(Packet):
self.foot.pack()
self.head.pack()
self.packed = ''.join([self.head.packed,
self.coat.packed or self.body.packed,
self.coat.packed,
self.foot.packed])
if self.size <= raeting.MAX_SEGMENT_SIZE:
@ -490,8 +502,8 @@ class TxPacket(Packet):
Create packeted segments from existing packet
'''
self.segments = odict()
fullsize = self.coat.size or self.body.size
full = self.coat.packed or self.body.packed
fullsize = self.coat.size
full = self.coat.packed
extra = 0
if self.data['hk'] == raeting.headKinds.json:
@ -509,12 +521,12 @@ class TxPacket(Packet):
segment = TxPacket( stack=self.stack,
data=self.data)
segment.data.update(sn=i, sc=segcount, )
segment.body.packed = haul
segment.data.update(sn=i, sc=segcount)
segment.coat.packed = segment.body.packed = haul
segment.foot.pack()
segment.head.pack()
segment.packed = ''.join([ segment.head.packed,
segment.body.packed,
segment.coat.packed,
self.foot.packed])
segment.sign()
self.segments[i] = segment
@ -636,13 +648,14 @@ class RxPacket(Packet):
'''
hl = self.data['hl']
fl = self.data['fl']
self.coat.packed = self.packed[hl:self.size - fl] #coat.parse loads body.packed
ck = self.data['ck']
#ck = self.data['ck']
if ck == raeting.coatKinds.nada:
self.body.packed = self.packed[hl:self.size - fl]
else:
self.coat.packed = self.packed[hl:self.size - fl] #coat.parse loads body.packed
#if ck == raeting.coatKinds.nada:
#self.body.packed = self.packed[hl:self.size - fl]
#else:
#self.coat.packed = self.packed[hl:self.size - fl] #coat.parse loads body.packed
def validateLengths(self):
'''
@ -680,7 +693,7 @@ class RxPacket(Packet):
Result is .body.data and .data
Raises PacketError exception If failure
'''
if not self.segmented:
if not self.segmented: #since head and foot are not valid
self.unpackInner()
self.coat.parse()
self.body.parse()
@ -712,8 +725,5 @@ class RxPacket(Packet):
haul = segment.packed[hl:segment.size - fl]
hauls.append(haul)
packed = "".join(hauls)
if self.data['ck'] != raeting.coatKinds.nada:
self.coat.packed = packed
else:
self.body.packed = packed
self.coat.packed = packed

View File

@ -45,6 +45,7 @@ header data =
ti: Transaction ID (TID) Default 0
tk: Transaction Kind (TrnsKind)
pk: Packet Kind (PcktKind)
pl: Packet Length (PcktLen)
dt: Datetime Stamp (Datetime) Default 0
oi: Order index (OrdrIndx) Default 0
@ -103,13 +104,15 @@ from ioflo.base.odicting import odict
UDP_MAX_SAFE_PAYLOAD = 548 # IPV4 MTU 576 - udp headers 28
# IPV6 MTU is 1280 but headers are bigger
MAX_SEGMENT_SIZE = 1024 # assuming IPV6 capable equipment
MAX_SEGMENT_COUNT = (2 ** 16) - 1
RAET_PORT = 7530
RAET_TEST_PORT = 7531
DEFAULT_SRC_HOST = ''
DEFAULT_DST_HOST = '127.0.0.1'
MAX_HEAD_LEN = 255
MAX_PACKET_SIZE = min(67107840, MAX_SEGMENT_SIZE * MAX_SEGMENT_COUNT) # assuming IPV6 capable equipment
MAX_HEAD_SIZE = 255
JSON_END = '\r\n\r\n'
VERSIONS = odict([('0.1', 0)])
@ -181,9 +184,12 @@ PACKET_DEFAULTS = odict([
('sp', RAET_PORT),
('dh', DEFAULT_DST_HOST),
('dp', RAET_PORT),
('ri', 'RAET'),
('vn', 0),
('pk', 0),
('pl', 0),
('hk', 0),
('hl', 0),
('vn', 0),
('sd', 0),
('dd', 0),
('cf', False),
@ -191,7 +197,6 @@ PACKET_DEFAULTS = odict([
('si', 0),
('ti', 0),
('tk', 0),
('pk', 0),
('dt', 0),
('oi', 0),
('pf', False),
@ -209,11 +214,13 @@ PACKET_DEFAULTS = odict([
])
PACKET_FIELDS = ['sh', 'sp', 'dh', 'dp',
'hk', 'hl', 'vn', 'sd', 'dd', 'cf', 'bf', 'si', 'ti', 'tk', 'pk',
'ri', 'vn', 'pk', 'pl', 'hk', 'hl',
'sd', 'dd', 'cf', 'bf', 'si', 'ti', 'tk',
'dt', 'oi', 'pf', 'sn', 'sc', 'sf', 'af',
'bk', 'bl', 'ck', 'cl', 'fk', 'fl', 'fg']
HEAD_FIELDS = ['hk', 'hl', 'vn', 'sd', 'dd', 'cf', 'bf', 'si', 'ti', 'tk', 'pk',
HEAD_FIELDS = ['ri', 'vn', 'pk', 'pl', 'hk', 'hl',
'sd', 'dd', 'cf', 'bf', 'si', 'ti', 'tk',
'dt', 'oi', 'pf', 'sn', 'sc', 'sf', 'af',
'bk', 'bl', 'ck', 'cl', 'fk', 'fl', 'fg']

View File

@ -15,10 +15,10 @@ from salt.transport.road.raet import (raeting, nacling, packeting,
def test():
data = odict(hk=1, bk=raeting.bodyKinds.json)
body = odict(msg='Hello Raet World', extra='what is this')
packet1 = packeting.TxPacket(embody=body, data=data, )
print packet1.body.data
packet1.pack()
print packet1.packed
packet0 = packeting.TxPacket(embody=body, data=data, )
print packet0.body.data
packet0.pack()
print packet0.packed
stuff = []
for i in range(300):
@ -27,24 +27,32 @@ def test():
stuff = "".join(stuff)
data.update(bk=raeting.bodyKinds.raw)
packet1 = packeting.TxPacket(embody=stuff, data=data, )
packet1.pack()
print packet1.packed
packet0 = packeting.TxPacket(embody=stuff, data=data, )
packet0.pack()
print packet0.packed
rejoin = []
if packet1.segmented:
for index, segment in packet1.segments.items():
if packet0.segmented:
for index, segment in packet0.segments.items():
print index, segment.packed
rejoin.append(segment.body.packed)
rejoin = "".join(rejoin)
print stuff == rejoin
signer = nacling.Signer()
masterSignKeyHex = signer.keyhex
masterVerKeyHex = signer.verhex
privateer = nacling.Privateer()
masterPriKeyHex = privateer.keyhex
masterPubKeyHex = privateer.pubhex
signer = nacling.Signer()
minionSignKeyHex = signer.keyhex
minionVerKeyHex = signer.verhex
privateer = nacling.Privateer()
minionPriKeyHex = privateer.keyhex
minionPubKeyHex = privateer.pubhex
#master stack
device = devicing.LocalDevice( did=1,
@ -52,65 +60,128 @@ def test():
prikey=masterPriKeyHex,)
stack0 = stacking.StackUdp(device=device)
data.update(fk=raeting.footKinds.nacl)
packet1 = packeting.TxPacket(stack=stack0, embody=stuff, data=data, )
packet1.pack()
print packet1.packed
remote1 = devicing.RemoteDevice( did=2,
verkey=minionVerKeyHex,
pubkey=minionPubKeyHex,)
stack0.addRemoteDevice(remote1)
#minion stack
device = devicing.LocalDevice( did=2,
ha=("", raeting.RAET_TEST_PORT),
signkey=minionSignKeyHex,
prikey=minionPriKeyHex,)
stack1 = stacking.StackUdp(device=device)
remote0 = devicing.RemoteDevice( did=1,
ha=('127.0.0.1', raeting.RAET_PORT),
verkey=masterVerKeyHex,
pubkey=masterPubKeyHex,)
stack1.addRemoteDevice(remote0)
remote0.publee = nacling.Publican(key=remote1.privee.pubhex)
remote1.publee = nacling.Publican(key=remote0.privee.pubhex)
data.update(sd=1, dd=2, bk=raeting.bodyKinds.raw, fk=raeting.footKinds.nacl)
packet0 = packeting.TxPacket(stack=stack0, embody=stuff, data=data, )
packet0.pack()
print packet0.packed
rejoin = []
if packet1.segmented:
for index, segment in packet1.segments.items():
if packet0.segmented:
for index, segment in packet0.segments.items():
print index, segment.packed
rejoin.append(segment.body.packed)
rejoin.append(segment.coat.packed)
rejoin = "".join(rejoin)
print stuff == rejoin
segmentage = None
if packet1.segmented:
for segment in packet1.segments.values():
#segment.parseOuter()
if segment.segmentive:
if packet0.segmented:
for segment in packet0.segments.values():
packet = packeting.RxPacket(stack=stack1, packed=segment.packed)
packet.parseOuter()
if packet.segmentive:
if not segmentage:
segmentage = packeting.RxPacket(stack=segment.stack,
data=segment.data)
segmentage.parseSegment(segment)
segmentage = packeting.RxPacket(stack=packet.stack,
data=packet.data)
segmentage.parseSegment(packet)
if segmentage.desegmentable():
segmentage.desegmentize()
break
if segmentage:
if not stack0.parseInner(segmentage):
if not stack1.parseInner(segmentage):
print "*******BAD SEGMENTAGE********"
return
print segmentage.body.packed
print segmentage.body.data
print segmentage.body.packed == packet0.body.packed
body = odict(stuff=stuff)
print body
data.update(bk=raeting.bodyKinds.json, fk=raeting.footKinds.nacl)
packet1 = packeting.TxPacket(stack=stack0, embody=body, data=data, )
packet1.pack()
print packet1.packed
data.update(sd=1, dd=2, bk=raeting.bodyKinds.json, fk=raeting.footKinds.nacl)
packet0 = packeting.TxPacket(stack=stack0, embody=body, data=data, )
packet0.pack()
print packet0.packed
segmentage = None
if packet1.segmented:
for segment in packet1.segments.values():
#segment.parseOuter()
if segment.segmentive:
if packet0.segmented:
for segment in packet0.segments.values():
packet = packeting.RxPacket(stack=stack1, packed=segment.packed)
packet.parseOuter()
if packet.segmentive:
if not segmentage:
segmentage = packeting.RxPacket(stack=segment.stack,
data=segment.data)
segmentage.parseSegment(segment)
segmentage = packeting.RxPacket(stack=packet.stack,
data=packet.data)
segmentage.parseSegment(packet)
if segmentage.desegmentable():
segmentage.desegmentize()
break
if segmentage:
if not stack0.parseInner(segmentage):
if not stack1.parseInner(segmentage):
print "*******BAD SEGMENTAGE********"
return
print segmentage.body.packed
print segmentage.body.data
print segmentage.body.packed == packet0.body.packed
body = odict(stuff=stuff)
print body
data.update(sd=1, dd=2,
bk=raeting.bodyKinds.json,
ck=raeting.coatKinds.nacl,
fk=raeting.footKinds.nacl)
packet0 = packeting.TxPacket(stack=stack0, embody=body, data=data, )
packet0.pack()
print "Body"
print packet0.body.size, packet0.body.packed
print "Coat"
print packet0.coat.size, packet0.coat.packed
print "Head"
print packet0.head.size, packet0.head.packed
print "Foot"
print packet0.foot.size, packet0.foot.packed
print "Packet"
print packet0.size, packet0.packed
segmentage = None
if packet0.segmented:
for segment in packet0.segments.values():
packet = packeting.RxPacket(stack=stack1, packed=segment.packed)
packet.parseOuter()
if packet.segmentive:
if not segmentage:
segmentage = packeting.RxPacket(stack=packet.stack,
data=packet.data)
segmentage.parseSegment(packet)
if segmentage.desegmentable():
segmentage.desegmentize()
break
if segmentage:
if not stack1.parseInner(segmentage):
print "*******BAD SEGMENTAGE********"
print segmentage.body.packed
print segmentage.body.data
print segmentage.body.packed == packet0.body.packed