mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 17:33:54 +00:00
Initial add of raet backend libs
This commit is contained in:
parent
2a7c10fe5b
commit
d2f3addfd5
7
salt/transport/road/__init__.py
Normal file
7
salt/transport/road/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
""" shrub modules"""
|
||||
#print "\nPackage at%s" % __path__[0]
|
||||
|
||||
__all__ = ['raet',]
|
||||
|
||||
for m in __all__:
|
||||
exec "from . import %s" % m #relative import
|
137
salt/transport/road/raet.flo
Normal file
137
salt/transport/road/raet.flo
Normal file
@ -0,0 +1,137 @@
|
||||
# Shrub dev FloScript
|
||||
|
||||
house shrub
|
||||
|
||||
init .raet.media.address to host "" port 7532
|
||||
|
||||
init raet.packet.tx.meta to hk 0 hl 0 nk 0 nl 0 bk 1 bl 0 tk 0 tl 0 \
|
||||
dh "127.0.0.1" dp 7533
|
||||
|
||||
init raet.packet.tx.head to hk 0 hl 0 vn 0 \
|
||||
sd 10 dd 20 cf 0 mf 0 si 1 ti 1 \
|
||||
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
|
||||
|
||||
init raet.packet.tx.neck to pack ""
|
||||
init raet.packet.tx.body to mid "shrubbery" fun "dumb" foo "bar"
|
||||
init raet.packet.tx.tail to pack ""
|
||||
init raet.packet.tx.pack to value ""
|
||||
init raet.packet.rx.pack to value ""
|
||||
|
||||
framer raeter be active first start
|
||||
frame start
|
||||
do raet server per inode ".raet.media."
|
||||
exit
|
||||
do raet server closer per inode ".raet.media."
|
||||
|
||||
framer shrubber be active first start
|
||||
frame start
|
||||
go next
|
||||
|
||||
frame compose
|
||||
enter
|
||||
do raet composer per inode ".raet.packet.tx."
|
||||
go next
|
||||
|
||||
frame pack
|
||||
enter
|
||||
do raet packer per inode ".raet.packet.tx."
|
||||
go next
|
||||
|
||||
frame transmit
|
||||
#copy .raet.packet.tx.pack into .raet.packet.rx.pack
|
||||
enter
|
||||
do raet transmitter per inode ".raet.packet.tx."
|
||||
go next
|
||||
|
||||
frame receive
|
||||
do raet receiver per inode ".raet.packet.rx."
|
||||
go next if update .raet.packet.rx.data
|
||||
|
||||
frame parse
|
||||
enter
|
||||
do raet parser per inode ".raet.packet.rx"
|
||||
go next
|
||||
|
||||
frame abort
|
||||
bid stop all
|
||||
|
||||
logger logger to log/ flush 1
|
||||
log outbody to outbody on fifo
|
||||
loggee outlog .raet.packet.tx.outlog
|
||||
log txraw to txraw on fifo
|
||||
loggee txlog .raet.media.txlog
|
||||
log rxraw to rxraw on fifo
|
||||
loggee rxlog .raet.media.rxlog
|
||||
log inbody to inbody on fifo
|
||||
loggee inlog .raet.packet.rx.inlog
|
||||
|
||||
|
||||
house bush
|
||||
|
||||
init .raet.media.address to host "" port 7533
|
||||
|
||||
init raet.packet.tx.meta to hk 0 hl 0 nk 0 nl 0 bk 1 bl 0 tk 0 tl 0 \
|
||||
dh "127.0.0.1" dp 7532
|
||||
|
||||
init raet.packet.tx.head to hk 0 hl 0 vn 0 \
|
||||
sd 10 dd 20 cf 0 mf 0 si 1 ti 1 \
|
||||
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
|
||||
|
||||
init raet.packet.tx.neck to pack ""
|
||||
init raet.packet.tx.body to mid "bushery" fun "doh" foo "baz"
|
||||
init raet.packet.tx.tail to pack ""
|
||||
init raet.packet.tx.pack to value ""
|
||||
init raet.packet.rx.pack to value ""
|
||||
|
||||
|
||||
framer ratter be active first start
|
||||
frame start
|
||||
do raet server per inode ".raet.media."
|
||||
exit
|
||||
do raet server closer per inode ".raet.media."
|
||||
|
||||
framer busher be active first start
|
||||
frame start
|
||||
go next
|
||||
|
||||
frame compose
|
||||
enter
|
||||
do raet composer per inode ".raet.packet.tx."
|
||||
go next
|
||||
|
||||
frame pack
|
||||
enter
|
||||
do raet packer per inode ".raet.packet.tx."
|
||||
go next
|
||||
|
||||
frame transmit
|
||||
#copy .raet.packet.tx.pack into .raet.packet.rx.pack
|
||||
enter
|
||||
do raet transmitter per inode ".raet.packet.tx."
|
||||
go next
|
||||
|
||||
frame receive
|
||||
do raet receiver per inode ".raet.packet.rx."
|
||||
go next if update .raet.packet.rx.data
|
||||
|
||||
frame parse
|
||||
enter
|
||||
do raet parser per inode ".raet.packet.rx"
|
||||
go next
|
||||
|
||||
frame abort
|
||||
bid stop all
|
||||
|
||||
logger logger to log/ flush 1
|
||||
log outbody to outbody on fifo
|
||||
loggee outlog .raet.packet.tx.outlog
|
||||
log txraw to txraw on fifo
|
||||
loggee txlog .raet.media.txlog
|
||||
log rxraw to rxraw on fifo
|
||||
loggee rxlog .raet.media.rxlog
|
||||
log inbody to inbody on fifo
|
||||
loggee inlog .raet.packet.rx.inlog
|
||||
|
||||
|
12
salt/transport/road/raet/__init__.py
Normal file
12
salt/transport/road/raet/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
""" raet modules
|
||||
|
||||
__init__.py file for raet package
|
||||
|
||||
"""
|
||||
#print "\nPackage at%s" % __path__[0]
|
||||
|
||||
__all__ = ['packeting', 'stacking', 'raeting']
|
||||
|
||||
for m in __all__:
|
||||
exec "from . import %s" % m #relative import
|
||||
|
306
salt/transport/road/raet/packeting.py
Normal file
306
salt/transport/road/raet/packeting.py
Normal file
@ -0,0 +1,306 @@
|
||||
""" packeting.py raet packet behaviors
|
||||
|
||||
See raeting.py for data format and packet field details.
|
||||
|
||||
Data format. The data from which a packet is created is a nested dict of dicts.
|
||||
What fields are included in a packed head, neck, body is dependent
|
||||
on the header kind, service kind, packet kind and defaults.
|
||||
To minimize lenght of JSON headers if field missing then the default is assumed
|
||||
|
||||
data =
|
||||
{
|
||||
meta: dict of meta data about packet
|
||||
{
|
||||
|
||||
}
|
||||
head: dict of header fields
|
||||
{
|
||||
|
||||
|
||||
pack: packed version of header
|
||||
}
|
||||
neck: dict of authentication fields
|
||||
{
|
||||
|
||||
pack: packed version of neck
|
||||
}
|
||||
body: dict of body fields
|
||||
{
|
||||
|
||||
pack: packed version of body
|
||||
}
|
||||
pack: packed version of whole packet on tx and raw packet on rx
|
||||
|
||||
}
|
||||
|
||||
"""
|
||||
#print "module %s" % __name__
|
||||
|
||||
from collections import deque
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
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 ioflo.base.consoling import getConsole
|
||||
console = getConsole()
|
||||
|
||||
from . import raeting
|
||||
|
||||
def CreateInstances(store):
|
||||
""" Create action instances. Recreate with each new house after clear registry
|
||||
|
||||
"""
|
||||
ComposerRaet(name='raetComposer', store=store).ioinits.update(
|
||||
data=odict(ipath='data', ival=odict(), iown='True'),
|
||||
meta='meta',
|
||||
head='head',
|
||||
neck='neck',
|
||||
body='body',
|
||||
tail='tail')
|
||||
|
||||
PackerRaet(name='raetPacker', store=store).ioinits.update(
|
||||
data=odict(ipath='data', ival=odict(), iown=True),
|
||||
outlog=odict(ipath='outlog', ival=odict(), iown=True),)
|
||||
|
||||
ParserRaet(name='raetParser', store=store).ioinits.update(
|
||||
data=odict(ipath='data', ival=odict(), iown=True),
|
||||
inlog=odict(ipath='inlog', ival=odict(), iown=True),)
|
||||
|
||||
TransmitterRaet(name='raetTransmitter', store=store).ioinits.update(
|
||||
data='data',
|
||||
txes=odict(ipath='.raet.media.txes', ival=deque()),)
|
||||
|
||||
ReceiverRaet(name='raetReceiver', store=store).ioinits.update(
|
||||
data='data',
|
||||
rxes=odict(ipath='.raet.media.rxes', ival=deque()), )
|
||||
|
||||
ServerRaet(name='raetServer', store=store).ioinits.update(
|
||||
txes=odict(ipath='txes', ival=deque(), iown=True),
|
||||
rxes=odict(ipath='rxes', ival=deque(), iown=True),
|
||||
connection=odict(ipath='connection', ival=None, iown=True),
|
||||
address=odict(ipath='address', ival=odict(host='', port=7530, ha=None)),
|
||||
txlog=odict(ipath='txlog', ival=odict(), iown=True),
|
||||
rxlog=odict(ipath='rxlog', ival=odict(), iown=True), )
|
||||
|
||||
CloserServerRaet(name='raetServerCloser', store=store).ioinits.update(
|
||||
connection=odict(ipath='connection', ival=None))
|
||||
|
||||
|
||||
class ComposerRaet(deeding.ParamDeed):
|
||||
""" ComposerRaet creates packet data as nested dicts from fields in
|
||||
share parms meta, head, neck, body, tail
|
||||
|
||||
inherited attributes
|
||||
.name is actor name string
|
||||
.store is data store ref
|
||||
.ioinits is dict of io init data for initio
|
||||
._parametric is flag for initio to not create attributes
|
||||
|
||||
"""
|
||||
Ioinits = odict(
|
||||
data=odict(ipath='data', ival=odict(), iown='True'),
|
||||
meta='meta',
|
||||
head='head',
|
||||
neck='neck',
|
||||
body='body',
|
||||
tail='tail')
|
||||
|
||||
def action(self, data, meta, head, neck, body, tail, **kwa):
|
||||
""" Build packet data from data section shares
|
||||
|
||||
"""
|
||||
dat = raeting.defaultData()
|
||||
dat['meta'].update(raeting.META_DEFAULTS)
|
||||
dat['meta'].update(meta.items())
|
||||
dat['head'].update(raeting.HEAD_DEFAULTS)
|
||||
dat['head'].update(head.items())
|
||||
dat['neck'].update(neck.items())
|
||||
dat['body'].update(data=odict(body.items()))
|
||||
dat['tail'].update(tail.items())
|
||||
data.value = dat
|
||||
return None
|
||||
|
||||
class PackerRaet(deeding.ParamDeed):
|
||||
""" PackerRaet creates a new packed RAET packet from data and fills in pack field
|
||||
|
||||
inherited attributes
|
||||
.name is actor name string
|
||||
.store is data store ref
|
||||
.ioinits is dict of io init data for initio
|
||||
._parametric is flag for initio to not create attributes
|
||||
|
||||
"""
|
||||
Ioinits = odict(
|
||||
data=odict(ipath='data', ival=odict(), iown=True),
|
||||
outlog=odict(ipath='outlog', ival=odict(), iown=True),)
|
||||
|
||||
def action(self, data, outlog, **kwa):
|
||||
""" Build packet from data"""
|
||||
if data.value:
|
||||
raeting.packPacket(data.value)
|
||||
data.stampNow()
|
||||
outlog.value[(data.value['meta']['dh'], data.value['meta']['dp'])] = data.value['body'].get('data', {})
|
||||
return None
|
||||
|
||||
class ParserRaet(deeding.ParamDeed):
|
||||
""" ParserRaet parses a packed RAET packet from pack and fills in data
|
||||
|
||||
inherited attributes
|
||||
.name is actor name string
|
||||
.store is data store ref
|
||||
.ioinits is dict of io init data for initio
|
||||
._parametric is flag for initio to not create attributes
|
||||
|
||||
"""
|
||||
Ioinits = odict(
|
||||
data=odict(ipath='data', ival=odict(), iown=True),
|
||||
inlog=odict(ipath='inlog', ival=odict(), iown=True),)
|
||||
|
||||
def action(self, data, inlog, **kwa):
|
||||
""" Parse packet from raw packed"""
|
||||
if data.value:
|
||||
data.value = raeting.defaultData(data.value)
|
||||
rest = raeting.parsePacket(data.value)
|
||||
data.stampNow()
|
||||
inlog.value[(data.value['meta']['sh'], data.value['meta']['sp'])] = data.value['body'].get('data', {})
|
||||
return None
|
||||
|
||||
class TransmitterRaet(deeding.ParamDeed):
|
||||
""" TransmitterRaet pushes packed packet in onto txes transmit deque and assigns
|
||||
destination ha from meta data
|
||||
|
||||
inherited attributes
|
||||
.name is actor name string
|
||||
.store is data store ref
|
||||
.ioinits is dict of io init data for initio
|
||||
._parametric is flag for initio to not create attributes
|
||||
|
||||
"""
|
||||
Ioinits = odict(
|
||||
data='data',
|
||||
txes=odict(ipath='.raet.media.txes', ival=deque()),)
|
||||
|
||||
def action(self, data, txes, **kwa):
|
||||
""" """
|
||||
if data.value:
|
||||
da = (data.value['meta']['dh'], data.value['meta']['dp'])
|
||||
txes.value.append((data.value['pack'], da))
|
||||
return None
|
||||
|
||||
class ReceiverRaet(deeding.ParamDeed):
|
||||
""" ReceiverRaet pulls packet from rxes deque and puts into new data
|
||||
and assigns meta data source ha using recieved ha
|
||||
|
||||
inherited attributes
|
||||
.name is actor name string
|
||||
.store is data store ref
|
||||
.ioinits is dict of io init data for initio
|
||||
._parametric is flag for initio to not create attributes
|
||||
|
||||
"""
|
||||
Ioinits = odict(
|
||||
data='data',
|
||||
rxes=odict(ipath='.raet.media.rxes', ival=deque()), )
|
||||
|
||||
def action(self, data, rxes, **kwa):
|
||||
""" """
|
||||
if rxes.value:
|
||||
rx, sa, da = rxes.value.popleft()
|
||||
data.value = raeting.defaultData()
|
||||
data.value['pack'] = rx
|
||||
data.value['meta']['sh'], data.value['meta']['sp'] = sa
|
||||
data.value['meta']['dh'], data.value['meta']['dp'] = da
|
||||
return None
|
||||
|
||||
class ServerRaet(deeding.ParamDeed):
|
||||
""" ServerRaet transmits and recieves udp packets from txes and rxes deques
|
||||
using sh, sp fields in sa server address (server host, server port) to receive on.
|
||||
Server is nonblocking socket connection
|
||||
|
||||
inherited attributes
|
||||
.name is actor name string
|
||||
.store is data store ref
|
||||
.ioinits is dict of io init data for initio
|
||||
._parametric is flag for initio to not create attributes
|
||||
|
||||
"""
|
||||
Ioinits = odict(
|
||||
txes=odict(ipath='txes', ival=deque(), iown=True),
|
||||
rxes=odict(ipath='rxes', ival=deque(), iown=True),
|
||||
connection=odict(ipath='connection', ival=None, iown=True),
|
||||
address=odict(ipath='address', ival=odict(host='', port=7530, ha=None)),
|
||||
txlog=odict(ipath='txlog', ival=odict(), iown=True),
|
||||
rxlog=odict(ipath='rxlog', ival=odict(), iown=True), )
|
||||
|
||||
def postinitio(self, connection, address, **kwa):
|
||||
""" Set up server to transmit and recive on address """
|
||||
connection.value = aiding.SocketNB(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))
|
||||
return None
|
||||
|
||||
def action(self, txes, rxes, connection, address, txlog, rxlog, **kwa):
|
||||
""" Receive any udp packets on server socket and put in rxes
|
||||
Send any packets in txes
|
||||
"""
|
||||
server = connection.value
|
||||
txl = txlog.value
|
||||
rxl = rxlog.value
|
||||
|
||||
if server:
|
||||
rxds = rxes.value
|
||||
while (True):
|
||||
rx, ra = server.receive() #if no data the tuple is ('',None)
|
||||
if not rx: # no received data so break
|
||||
break
|
||||
rxds.append((rx, ra, address.data.ha))
|
||||
rxl[ra] = rx
|
||||
|
||||
txds = txes.value
|
||||
while txds:
|
||||
tx, ta = txds.popleft()
|
||||
server.send(tx, ta)
|
||||
txl[ta] = tx
|
||||
|
||||
return None
|
||||
|
||||
class CloserServerRaet(deeding.ParamDeed):
|
||||
""" CloserServerRaet closes server socket connection
|
||||
|
||||
inherited attributes
|
||||
.name is actor name string
|
||||
.store is data store ref
|
||||
.ioinits is dict of io init data for initio
|
||||
._parametric is flag for initio to not create attributes
|
||||
|
||||
"""
|
||||
Ioinits = odict(
|
||||
connection=odict(ipath='connection', ival=None))
|
||||
|
||||
def action(self, connection, **kwa):
|
||||
""" Receive any udp packets on server socket and put in rxes
|
||||
Send any packets in txes
|
||||
"""
|
||||
if connection.value:
|
||||
connection.value.close()
|
||||
return None
|
||||
|
||||
def Test():
|
||||
"""Module Common self test
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Test()
|
458
salt/transport/road/raet/raeting.py
Normal file
458
salt/transport/road/raet/raeting.py
Normal file
@ -0,0 +1,458 @@
|
||||
""" raeting module provides constants and values for the RAET protocol
|
||||
|
||||
|
||||
Python Data format.
|
||||
The data from which a packet is created is a nested dict of dicts.
|
||||
What fields are included in a header is dependent on the meta data and the
|
||||
header kind, service kind, packet kind and defaults as well as the neck body and tail.
|
||||
|
||||
Header encoding.
|
||||
When the head kind is json = 0,then certain optimizations are
|
||||
used to minimize the header length.
|
||||
The header field keys are two bytes long
|
||||
If a header field value is the default then the field is not included
|
||||
Lengths are encoded as hex strings
|
||||
The flags are encoded as a double char hex string in field 'fg'
|
||||
|
||||
data =
|
||||
{
|
||||
meta: dict of meta data about packet
|
||||
{
|
||||
sh: source host ip address (ipv4) Default: ''
|
||||
sp: source ip port Default: 7532
|
||||
dh: destination host ip address (ipv4) Default: '127.0.0.1'
|
||||
dp: destination host ip port Default 7532
|
||||
hk: header kind (HeadKind) Default 0
|
||||
hl: header length (HeadLen) Default 0
|
||||
nk: Neck header kind (NeckKind) Default '00' hs
|
||||
nl: Neck header length (NeckLen) Default 0
|
||||
bk: body kind (BodyKind) Default 0
|
||||
bl: body length (BodyLen) Default 0
|
||||
tk: tail kind (TailKind) Default 0
|
||||
tl: tail length (TailLen) Default 0
|
||||
}
|
||||
head: dict of header fields
|
||||
{
|
||||
hk: header kind (HeadKind) Default 0
|
||||
hl: header length (HeadLen) Default 0
|
||||
|
||||
vn: version (Version) Default 0
|
||||
|
||||
sd: Source Device ID (SDID)
|
||||
dd: Destination Device ID (DDID)
|
||||
cf: Corresponder Flag (CrdrFlag) Default 0
|
||||
mf: Multicast Flag (MultFlag) 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
|
||||
|
||||
oi: order index (OrdrIndx) Default 0
|
||||
dt: Datetime Stamp (Datetime) Default 0
|
||||
|
||||
sn: Segment Number (SegNum) Default 0
|
||||
sc: Segment Count (SegCnt) Default 1
|
||||
|
||||
pf: Pending Segment Flag (PendFlag) Default 0
|
||||
Not the last segment more pending
|
||||
af: All Flag (AllFlag) Default 0
|
||||
Resend all segments not just one
|
||||
|
||||
nk: Neck header kind (NeckKind) Default '00' hs
|
||||
nl: Neck header length (NeckLen) Default 0
|
||||
|
||||
bk: body kind (BodyKind) Default '00' hs
|
||||
bl: body length (BodyLen) Default 0
|
||||
|
||||
tk: tail kind (TailKind) Default '00' hs
|
||||
tl: tail length (TailLen) Default 0
|
||||
|
||||
fg: flags packed (Flags) Default '00' hs
|
||||
2 byte Hex string with bits (0, 0, af, pf, 0, bf, mf, cf)
|
||||
Zeros are TBD flags
|
||||
|
||||
pack: packed version of header
|
||||
}
|
||||
neck: dict of authentication fields
|
||||
{
|
||||
pack: packed version of neck
|
||||
}
|
||||
body: dict of body fields
|
||||
{
|
||||
pack: packed version of body
|
||||
}
|
||||
tail: dict of tail fields
|
||||
{
|
||||
pack: packed version of tail
|
||||
}
|
||||
pack: packed version of whole packet on tx and raw packet on rx
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
import struct
|
||||
|
||||
from collections import namedtuple, Mapping
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
|
||||
from ioflo.base.odicting import odict
|
||||
from ioflo.base.aiding import SocketNB
|
||||
|
||||
|
||||
MAX_HEAD_LEN = 255
|
||||
JSON_END = '\r\n\r\n'
|
||||
|
||||
DATA_PARTS = ['meta', 'head', 'neck', 'body', 'tail']
|
||||
|
||||
HEAD_KINDS = odict([('json', 0), ('binary', 1), ('unknown', 255)])
|
||||
HEAD_KIND_NAMES = odict((v,k) for k, v in HEAD_KINDS.iteritems()) # inverse map
|
||||
HeadKind = namedtuple('HeadKind', HEAD_KINDS.keys())
|
||||
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),
|
||||
('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),
|
||||
('crc64', 8), ('unknown', 0)])
|
||||
NeckSize = namedtuple('NeckSize', NECK_SIZES.keys())
|
||||
neckSizes= NeckSize(**NECK_SIZES)
|
||||
|
||||
BODY_KINDS = odict([('nada', 0), ('json', 1), ('binary', 1), ('unknown', 255)])
|
||||
BODY_KIND_NAMES = odict((v,k) for k, v in BODY_KINDS.iteritems()) # inverse map
|
||||
BodyKind = namedtuple('BodyKind', BODY_KINDS.keys())
|
||||
bodyKinds = BodyKind(**BODY_KINDS)
|
||||
|
||||
TAIL_KINDS = odict([('nada', 0), ('crc16', 1), ('crc64', 2),('unknown', 255)])
|
||||
TAIL_KIND_NAMES = odict((v,k) for k, v in TAIL_KINDS.iteritems()) # inverse map
|
||||
TailKind = namedtuple('TailKind', TAIL_KINDS.keys())
|
||||
tailKinds = TailKind(**TAIL_KINDS)
|
||||
|
||||
# bytes
|
||||
TAIL_SIZES = odict([('nada', 0), ('crc16', 2), ('crc64', 8),('unknown', 0)])
|
||||
TailSize = namedtuple('TailSize', TAIL_SIZES.keys())
|
||||
tailSizes= TailSize(**TAIL_SIZES)
|
||||
|
||||
SERVICE_KINDS = odict([('fireforget', 0), ('ackretry', 1), (
|
||||
'unknown', 255)])
|
||||
SERVICE_KIND_NAMES = odict((v,k) for k, v in SERVICE_KINDS.iteritems()) # inverse map
|
||||
ServiceKind = namedtuple('ServiceKind', SERVICE_KINDS.keys())
|
||||
serviceKinds = ServiceKind(**SERVICE_KINDS)
|
||||
|
||||
PACKET_KINDS = odict([('data', 0), ('req', 1), ('ack', 8),
|
||||
('nack', 9), ('unknown', 255)])
|
||||
PACKET_KIND_NAMES = odict((v,k) for k, v in PACKET_KINDS.iteritems()) # inverse map
|
||||
PacketKind = namedtuple('PacketKind', PACKET_KINDS.keys())
|
||||
packetKinds = PacketKind(**PACKET_KINDS)
|
||||
|
||||
|
||||
# default values of meta data, if given, lengths are integers
|
||||
META_DEFAULTS = odict( [
|
||||
('sh', ''),
|
||||
('sp', 7530),
|
||||
('dh', '127.0.0.1'),
|
||||
('dp', 7530),
|
||||
('vn', 0),
|
||||
('hk', None),
|
||||
('hl', None),
|
||||
('nk', 0),
|
||||
('nl', 0),
|
||||
('bk', 0),
|
||||
('bl', 0),
|
||||
('tk', 0),
|
||||
('tl', 0),
|
||||
])
|
||||
|
||||
# head fields that may be included in json header if not default value
|
||||
HEAD_DEFAULTS = odict( [
|
||||
('hk', None),
|
||||
('hl', None),
|
||||
('vn', 0),
|
||||
('sd', None),
|
||||
('dd', None),
|
||||
('cf', 0),
|
||||
('mf', 0),
|
||||
('si', 0),
|
||||
('ti', 0),
|
||||
('sk', None),
|
||||
('pk', None),
|
||||
('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),
|
||||
])
|
||||
|
||||
META_LEN_FIELDS = ['nl', 'bl', 'tl'] # note 'hl' is special so not here
|
||||
META_KIND_FIELDS = ['nk', 'bk', 'tk'] # note 'hk' is special so not here
|
||||
|
||||
def defaultData(data=None):
|
||||
""" Returns defaulted data"""
|
||||
if data is None:
|
||||
data = odict()
|
||||
for part in DATA_PARTS: # make sure all parts in data
|
||||
if part not in data:
|
||||
data[part] = odict()
|
||||
if 'pack' not in data:
|
||||
data['pack'] = ''
|
||||
return data
|
||||
|
||||
def updateMissing(kit, defaults):
|
||||
""" Update kit dict with item from default if item missing in kit"""
|
||||
for k, v in defaults.items():
|
||||
if k not in kit:
|
||||
kit[k] = v
|
||||
|
||||
def packPacket(data):
|
||||
""" Uses data to create packed version and assigns to pack field in data
|
||||
Also returns packed packet
|
||||
"""
|
||||
meta = data['meta']
|
||||
head = data['head']
|
||||
neck = data['neck']
|
||||
body = data['body']
|
||||
tail = data['tail']
|
||||
|
||||
packBody(meta, body)
|
||||
packTail(meta, body, tail)
|
||||
packHead(meta, head)
|
||||
packNeck(meta, head, neck)
|
||||
data['pack'] = '{0}{1}{2}{3}'.format(head['pack'], neck['pack'], body['pack'], tail['pack'])
|
||||
return (data['pack'])
|
||||
|
||||
|
||||
def packBody(meta, body):
|
||||
""" Uses meta, and body data to create packed version updates fields in body"""
|
||||
body['pack'] = ''
|
||||
if meta.get('bk') == bodyKinds.json:
|
||||
kit = body.get('raw', '') or body.get('data', {})
|
||||
packed = json.dumps(kit, separators=(',', ':'))
|
||||
body['pack'] = packed
|
||||
meta['bl'] = len(body['pack'])
|
||||
|
||||
def packTail(meta, body, tail):
|
||||
""" Uses meta, and body data to create packed version of tail and updates meta and tail"""
|
||||
tail['pack'] = ''
|
||||
if meta.get('tk') == tailKinds.nada:
|
||||
pass
|
||||
meta['tl'] = len(tail['pack'])
|
||||
|
||||
def packHead(meta, head):
|
||||
""" Uses meta and head data to create packed version and assigns to pack field in head"""
|
||||
meta['error'] = ''
|
||||
head['pack'] = ''
|
||||
if head.get('hk') == headKinds.json:
|
||||
kit = odict()
|
||||
|
||||
for field in META_LEN_FIELDS:
|
||||
head[field] = meta[field]
|
||||
for field in META_KIND_FIELDS:
|
||||
head[field] = meta[field]
|
||||
|
||||
for k, v in HEAD_DEFAULTS.items():
|
||||
if v is None:
|
||||
kit[k] = head[k]
|
||||
else:
|
||||
if head[k] != v:
|
||||
kit[k] = head[k]
|
||||
|
||||
kit['hl'] = '00' #need hex string so fixed length and jsonable
|
||||
packed = json.dumps(kit, separators=(',', ':'), encoding='ascii',)
|
||||
packed = "{0}{1}".format(packed, JSON_END)
|
||||
hl = len(packed)
|
||||
if hl > MAX_HEAD_LEN:
|
||||
meta['error'] = "Head length of {0}, exceeds max of {1}".format(hl, MAX_HEAD_LEN)
|
||||
meta['hl'] = 0
|
||||
return
|
||||
meta['hl'] = head['hl'] = hl
|
||||
#subsitute true length converted to 2 byte hex string
|
||||
packed = packed.replace('"hl":"00"', '"hl":"{0}"'.format("{0:02x}".format(hl)[-2:]), 1)
|
||||
head['pack'] = packed
|
||||
|
||||
def packNeck(meta, head, neck):
|
||||
""" Signs the head and puts auth signature into neck"""
|
||||
neck['pack'] = ''
|
||||
if meta.get('nk') == neckKinds.nada:
|
||||
pass
|
||||
meta['nl'] = len(neck['pack'])
|
||||
|
||||
def parsePacket(data):
|
||||
""" Parses raw packet data in data['pack'] and updates data
|
||||
"""
|
||||
meta = data['meta']
|
||||
head = data['head']
|
||||
neck = data['neck']
|
||||
body = data['body']
|
||||
tail = data['tail']
|
||||
pack = data['pack']
|
||||
|
||||
updateMissing(meta, META_DEFAULTS)
|
||||
|
||||
meta['error'] = ''
|
||||
|
||||
rest = parseHead(pack, meta, head)
|
||||
rest = parseNeck(rest, meta, neck)
|
||||
if not vouchHead(meta, head, neck):
|
||||
return
|
||||
rest = parseBody(rest, meta, body)
|
||||
rest = parseTail(rest, meta, tail)
|
||||
if not verifyBody(meta, head, tail):
|
||||
return
|
||||
|
||||
return rest
|
||||
|
||||
def parseHead(pack, meta, head):
|
||||
""" Parses and removes head from pack and returns remainder
|
||||
updates meta and head dicts:"""
|
||||
|
||||
meta['error'] = ''
|
||||
#need to test for Header type and version
|
||||
if pack.startswith('{"hk":0,') and JSON_END in pack: #json header
|
||||
meta['hk'] = headKinds.json
|
||||
front, sep, back = pack.partition(JSON_END)
|
||||
pack = back
|
||||
head['pack'] = "{0}{1}".format(front, sep)
|
||||
meta['hl'] = len(head['pack'])
|
||||
|
||||
head.update(HEAD_DEFAULTS)
|
||||
kit = json.loads( front,
|
||||
encoding='ascii',
|
||||
object_pairs_hook=odict)
|
||||
head.update(kit)
|
||||
|
||||
hl = int(head['hl'], 16)
|
||||
if hl != meta['hl']:
|
||||
meta['error'] = 'Actual head length does not match head field value.'
|
||||
|
||||
if head['hk'] != meta['hk']:
|
||||
meta['error'] = 'Actual head kind does not match head field value.'
|
||||
|
||||
for field in META_LEN_FIELDS:
|
||||
meta[field] = head[field]
|
||||
for field in META_KIND_FIELDS:
|
||||
meta[field] = head[field]
|
||||
|
||||
else: #notify unrecognizible packet
|
||||
meta['hl'] = 0
|
||||
meta['hk'] = headKinds.unknown
|
||||
meta['error'] = "Unrecognizible packet head."
|
||||
|
||||
return pack
|
||||
|
||||
def parseNeck(pack, meta, neck):
|
||||
""" Parses and removes neck from pack and returns remainder
|
||||
updates meta and neck dicts.
|
||||
"""
|
||||
|
||||
meta['error'] = ''
|
||||
nl = meta.get('nl', 0)
|
||||
neck['pack'] = pack[:nl]
|
||||
pack = pack[nl:]
|
||||
|
||||
if meta.get('nk') == neckKinds.nada:
|
||||
pass
|
||||
|
||||
else: #notify unrecognizible packet
|
||||
meta['nl'] = 0
|
||||
meta['nk'] = neckKinds.unknown
|
||||
meta['error'] = "Unrecognizible packet neck."
|
||||
|
||||
return pack
|
||||
|
||||
def parseBody(pack, meta, body):
|
||||
""" Parses and removes head from pack and returns remainder
|
||||
updates meta and body dicts:"""
|
||||
|
||||
meta['error'] = ''
|
||||
body['raw']= ''
|
||||
bl = meta.get('bl', 0)
|
||||
body['pack'] = pack[:bl]
|
||||
pack = pack[bl:]
|
||||
|
||||
if meta.get('bk') == bodyKinds.json:
|
||||
if bl:
|
||||
kit = json.loads(body['pack'], object_pairs_hook=odict)
|
||||
if isinstance(kit, Mapping):
|
||||
body['data'] = kit
|
||||
else:
|
||||
body['raw'] = kit
|
||||
|
||||
else: #notify unrecognizible packet
|
||||
meta['bl'] = 0
|
||||
meta['bk'] = bodyKinds.unknown
|
||||
meta['error'] = "Unrecognizible packet body."
|
||||
|
||||
return pack
|
||||
|
||||
def parseTail(pack, meta, tail):
|
||||
""" Parses and removes tail from pack and returns remainder
|
||||
updates meta and tail dicts.
|
||||
"""
|
||||
|
||||
meta['error'] = ''
|
||||
tl = meta.get('tl', 0)
|
||||
tail['pack'] = pack[:tl]
|
||||
pack = pack[tl:]
|
||||
|
||||
if meta.get('tk') == tailKinds.nada:
|
||||
pass
|
||||
|
||||
else: #notify unrecognizible packet
|
||||
meta['tl'] = 0
|
||||
meta['tk'] = tailKinds.unknown
|
||||
meta['error'] = "Unrecognizible packet tail."
|
||||
|
||||
return pack
|
||||
|
||||
def vouchHead(meta, head, neck):
|
||||
""" Uses signature in neck to vouch for (authenticate) head
|
||||
"""
|
||||
#meta['error'] = "Head failed authentication."
|
||||
return True
|
||||
|
||||
def verifyBody(meta, body, tail):
|
||||
""" Uses tail to verify body does not have errors
|
||||
"""
|
||||
#meta['error'] = "Body failed verification."
|
||||
return True
|
||||
|
||||
def sendPacket(data):
|
||||
""" Uses data to create packed version and assigns to pack field in data
|
||||
Also returns packed packet
|
||||
"""
|
||||
meta = data['meta']
|
||||
head = data['head']
|
||||
neck = data['neck']
|
||||
body = data['body']
|
||||
tail = data['tail']
|
||||
|
||||
packBody(meta, body)
|
||||
packTail(meta, body, tail)
|
||||
packHead(meta, head)
|
||||
packNeck(meta, head, neck)
|
||||
data['pack'] = '{0}{1}{2}{3}'.format(head['pack'], neck['pack'], body['pack'], tail['pack'])
|
||||
|
||||
return (data['pack'])
|
18
salt/transport/road/raet/stacking.py
Normal file
18
salt/transport/road/raet/stacking.py
Normal file
@ -0,0 +1,18 @@
|
||||
""" packeting.py raet protocol stacking behaviors
|
||||
|
||||
"""
|
||||
|
||||
#print "module %s" % __name__
|
||||
|
||||
from collections import deque
|
||||
|
||||
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 ioflo.base.consoling import getConsole
|
||||
console = getConsole()
|
||||
|
Loading…
Reference in New Issue
Block a user