-
Notifications
You must be signed in to change notification settings - Fork 21
/
packets.py
145 lines (115 loc) · 4.94 KB
/
packets.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#----IMPORTS------------
from gestalt import utilities
#--PACKETS--------------
#
# A Gestalt class for encoding and decoding data packets
class packetHolder(object):
def __init__(self):
self.Packet = {} #empty packet
def put(self, Packet):
self.Packet = Packet
def get(self):
return self.Packet
class packetSet(object):
def __init__(self, Packet):
self.Packet = Packet
def __call__(self, updateInput):
if type(updateInput) == dict: #only one packet in packetSet
packetSet = [self.Packet(updateInput)]
if type(updateInput) == list: #multiple packets in packetSet
packetSet = [self.Packet(inputDict) for inputDict in updateInput]
return packetSet
#base class for tokens
class packetToken(object):
def __call__(self, *args, **kwargs): #by default, a call to class will return encoded list
return self.encode(*args, **kwargs)
def encode(self, *args, **kwargs):
pass
def decode(self, *args, **kwargs):
pass
#converts integers into byte stream, and vice versa
class pInteger(packetToken):
def __init__(self, keyName, numBytes):
self.keyName = keyName #keyName stores the key of the relevant data in the inputDict
self.numBytes = numBytes #number of bytes to reserve for the integer
def encode(self, inputDict):
return utilities.intToBytes(inputDict[self.keyName], self.numBytes)
def decode(self, inputPacket):
inputSlice = inputPacket[:self.numBytes] #the component of the packet relevant to this token
outputSlice = inputPacket[self.numBytes:] #the component of the packet relevant to future tokens
return {self.keyName:utilities.bytesToInt(inputSlice)}, outputSlice
#passes thru lists, and converts strings into lists
class pList(packetToken):
def __init__(self, keyName, numBytes = False):
self.keyName = keyName
self.numBytes = numBytes
def encode(self, inputDict):
inputPhrase=inputDict[self.keyName] #input phrase to be encoded
if type(inputPhrase) == str: #input is string, must convert into a list
print "WARNING in pList: Expected list, got a string."
inputPhrase = [ord(char) for char in inputPhrase]
if type(inputPhrase) != list and type(inputPhrase) != packet:
print "ERROR in pList: Must provide either a list or a string."
return False
if self.numBytes and (len(inputPhrase) != self.numBytes): #only complain if number of bytes has been specified
print "WARNING in pList: " + str(len(inputPhrase)) + " bytes encoded, but "+ str(self.numBytes) + " bytes expected."
return inputPhrase
def decode(self, inputPacket):
if self.numBytes:
if len(inputPacket)<self.numBytes:
print ""
return {self.keyName:inputPacket[:self.numBytes]}, inputPacket[self.numBytes:]
else:
return {self.keyName:inputPacket}, []
#passes thru lists, and converts strings into lists
class pString(packetToken):
def __init__(self, keyName, numBytes = False):
self.keyName = keyName
self.numBytes = numBytes
def encode(self, inputDict):
inputPhrase=inputDict[self.keyName] #input phrase to be encoded
if type(inputPhrase) == str: #input is string, must convert into a list
inputPhrase = [ord(char) for char in inputPhrase]
if type(inputPhrase) == list:
print "WARNING in pString: Expected string, got a list."
if type(inputPhrase) != list and type(inputPhrase) != packet:
print "ERROR in pString: Must provide either a list or a string."
return False
if self.numBytes and (len(inputPhrase) != self.numBytes): #only complain if number of bytes has been specified
print "WARNING in pString: " + str(len(inputPhrase)) + " bytes encoded, but "+ str(self.numBytes) + " bytes expected."
return inputPhrase
def decode(self, inputPacket):
if self.numBytes:
inputSlice = inputPacket[:self.numBytes]
outputSlice = inputPacket[self.numBytes:]
else:
inputSlice = inputPacket
outputSlice = []
return {self.keyName:''.join([chr(char) for char in inputSlice])}, outputSlice
class packet(list): #packets are represented as a list subclass with templating abilities
def __init__(self, template, value = None):
if type(template) == list: self.template = template
if type(template) == packet: #inherit packet from provided packet
self.template = template.template
if value == None: value = []
list.__init__(self, value)
def __call__(self, inputDict):
templatedList = []
for token in self.template: #build output list
templatedList += token(inputDict)
outputList =[len(templatedList) if type(outputItem)==pLength else outputItem for outputItem in templatedList]
return packet(self.template, outputList)
def spawn(self, outputList):
return packet(self.template, outputList)
def decode(self, decodeList = None):
if decodeList == None: decodeList = list(self)
decodedDict = {}
for token in self.template:
dictFrag, decodeList = token.decode(decodeList)
decodedDict.update(dictFrag)
return decodedDict
class pLength(packetToken):
def encode(self, inputDict):
return [self]
def decode(self, inputPacket):
return {}, inputPacket[1:]