The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
frameinfo.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 '''
3 A collection of classes which provide constants for FrameTypes and FrameSetTypes
4 '''
5 
6 import re
7 #from AssimCclasses import pyFrame, pyAddrFrame, pySignFrame, pySeqnoFrame, \
8 # pyIntFrame, pyCstringFrame, pyNVpairFrame, pyIpPortFrame
9 
10 #pylint: disable=R0903
11 
12 class pyFrame:
13  'Placeholder bootstrapping class'
14  def __init__(self):
15  pass
16 
17 class pyAddrFrame:
18  'Placeholder bootstrapping class'
19  def __init__(self):
20  pass
21 
22 class pySignFrame:
23  'Placeholder bootstrapping class'
24  def __init__(self):
25  pass
26 
27 class pySeqnoFrame:
28  'Placeholder bootstrapping class'
29  def __init__(self):
30  pass
31 
32 class pyIntFrame:
33  'Placeholder bootstrapping class'
34  def __init__(self):
35  pass
36 
37 class pyCstringFrame:
38  'Placeholder bootstrapping class'
39  def __init__(self):
40  pass
41 
42 class pyNVpairFrame:
43  'Placeholder bootstrapping class'
44  def __init__(self):
45  pass
46 
47 class pyIpPortFrame:
48  'Placeholder bootstrapping class'
49  def __init__(self):
50  pass
51 
52 class pyCryptFrame:
53  'Placeholder bootstrapping class'
54  def __init__(self):
55  pass
56 
57 class pyCompressFrame:
58  'Placeholder class'
59  def __init__(self):
60  pass
61 
62 class FrameTypes:
63  'Class defining the universe of FrameSets - including code to generate a C header file'
64  fileheader = \
65 '''
66 /**
67  * @file
68  * @brief Header file defining the data layouts for our Frames.
69  * THIS FILE MECHANICALLY GENERATED by "%s". DO NOT EDIT.
70  *
71  *
72  * This file is part of the Assimilation Project.
73  *
74  * @author Copyright &copy; 2011, 2012 - Alan Robertson <alanr@unix.sh>
75  * @n
76  * The Assimilation software is free software: you can redistribute it and/or modify
77  * it under the terms of the GNU General Public License as published by
78  * the Free Software Foundation, either version 3 of the License, or
79  * (at your option) any later version.
80  *
81  * The Assimilation software is distributed in the hope that it will be useful,
82  * but WITHOUT ANY WARRANTY; without even the implied warranty of
83  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84  * GNU General Public License for more details.
85  *
86  * You should have received a copy of the GNU General Public License
87  * along with the Assimilation Project software. If not, see http://www.gnu.org/licenses/
88  */
89 /**
90 @addtogroup FrameFormats
91 @{
92  Below is the set of frame formats and corresponding macro definitions
93  This section will document the format of the individual frame types.
94  The first frame in a frameset must be a signature frame.
95  If an encryption frame is present, it must be the frame in the frameset.
96  If a compression frame is present, it must occur after the encryption frame
97  if present, or after the signature frame, if there is no encryption frame.
98 
99  The final frame in a frameset must be an End frame (which will be
100  added automatically by the @ref FrameSet marshalling classes).
101 @}
102 */
103 /**
104 @defgroup IndividualFrameFormats Individual TLV 'Frame' data types and layouts (by TLV type)
105 @{
106 Below is the set of individual frame types and data layouts - organized by TLV type.
107 Note that a given @ref Frame subclass can appear be associated with many different TLV types.
108 This file organizes this data by the TLV type, not by the underlying @ref Frame subclass.
109 @ingroup FrameFormats
110 @ingroup DefineEnums
111 @{
112 */
113 '''
114  asciiart = {
115  'pyFrame':
116 '''
117 +----------------+-----------+------------------+
118 | frametype = %2d | f_length | frame data |
119 | (16 bits) | (16-bits) | (f_length bytes) |
120 +----------------+-----------+------------------+
121 ''',
122  'pySignFrame':
123 '''
124 +----------------+-----------+-----------------+--------------------+
125 | frametype = %2d | f_length | signature-type | digital signature |
126 | (16 bits) | (16-bits) | (16 bits) | (f_length-2 bytes) |
127 +----------------+-----------+-----------------+--------------------+
128 ''',
129  'pyCryptFrame':
130 '''
131 +----------------+-----------+-------------------------+
132 | frametype = %2d | f_length | encryption information |
133 | (16 bits) | (16-bits) | (f_length bytes) |
134 +----------------+-----------+-------------------------+
135 ''',
136  'pyCompressFrame':
137 '''
138 +----------------+-----------+------------------------+
139 | frametype = %2d | f_length | compression information|
140 | (16 bits) | (16-bits) | (f_length bytes) |
141 +----------------+-----------+------------------------+
142 ''',
143  'pySeqnoFrame':
144 '''
145 +----------------+---------------+-------------+-----------+
146 | frametype = %2d | f_length = 8 | reply id | queue id |
147 | (16 bits) | (16-bits) | (8 bytes) | (2 bytes) |
148 +----------------+---------------+-------------+-----------+
149 ''',
150 
151  'pyIntFrame':
152 '''
153 +----------------+--------------+-------------------------+
154 | frametype = %2d | f_length = | integer value |
155 | | 1,2,3,4 or 8 | value |
156 | (16 bits) | (16-bits) | (1,2,3,4,or 8 bytes) |
157 +----------------+--------------+-------------------------+
158 ''',
159  'pyCstringFrame':
160 '''
161 +----------------+----------------+----------------+--------+
162 | frametype = %2d | f_length = 'n' | interface name | 0x00 |
163 | (16 bits) | (16-bits) | (n-1 bytes) | 1 byte |
164 +----------------+----------------+----------------+--------+
165 ''',
166  'pyAddrFrame':
167 '''
168 +----------------+----------------+---------------+--------------+
169 | frametype = %2d | f_length = n | Address Type | address |
170 | (16 bits) | (16-bits) | 2 bytes | (n-2 bytes) |
171 +----------------+----------------+---------------+--------------+
172 ''',
173  'pyIpPortFrame':
174 '''
175 +----------------+----------------+-------------+--------------+---------------+
176 | frametype = %2d | f_length = n | Port Number | Address Type | address |
177 | (16 bits) | (16-bits) | 2 bytes | 2 bytes | (n-4 bytes) |
178 +----------------+----------------+-------------+--------------+---------------+
179 ''',
180  'pyNVpairFrame':
181 '''
182 +----------------+---------------+--------+-----------------+-------+------+
183 | frametype = %2d | f_length = n | nm_len | name | NUL | | NUL |
184 | (16 bits) | (16-bits) | 1 byte | nm_len-1 | byte | value | byte |
185 | | |(8 bits)| bytes | | | |
186 +----------------+---------------+--------+-----------------+-------+------+
187 ''',
188 
189 }
190  intframetypes = {
191  0: (pyFrame, 'END', 'Final frame in a message',
192 '''The last frame in a frameset is required to be an End frame.
193 End frames are of type zero and <b>always</b> have length zero.
194 Its corresponding class is @ref Frame.
195 This is the most basic Frame type, and is the only frame type that permits a length of zero.
196 '''),
197  1: (pySignFrame, 'SIG', 'Digital signature frame',
198 '''The signature frame is mandatory and must be the first
199 frame in the frameset - and must have frametype <b>1</b>.
200 The digital signature computed in the digital signature field is computed
201 on all the bytes in the frameset beginning with the first byte after
202 the end of this frame, extending through and including the last byte of the frameset.
203 Note that this will include the encryption frame if present.
204 The format and length of the digital signature depends on the type of signature.
205 '''),
206  2: (pyCryptFrame, 'CRYPT', 'Encryption frame',
207 '''If an encryption frame is present it must be the second
208 frame in the frameset, and can only be preceded by a @ref FRAMETYPE_SIG frame.
209 It must have frametype <b>2</b>.
210 When this frame is present, then all the frames following
211 are encrypted according information in the encryption information value segment.
212 '''),
213  3: (pyCompressFrame, 'COMPRESS', 'Compression frame',
214 '''If a compression frame is present (<b>frametype = 3</b>) it must be the second
215 or third frame in the frameset, and can only be preceded by a @ref FRAMETYPE_SIG
216 and @ref FRAMETYPE_CRYPT frames.
217 When this frame is present, then all the frames following
218 are compreseed according information in the compression information value segment.
219 The format of the compression information value segment will likely be a
220 single integer saying which compression method was used.
221 '''),
222  4: (pySeqnoFrame, 'REQID', 'Request ID - a message sequence number.',
223 '''Requests from the central authority are identified by a request id
224 (basically a sequence number) and a queue id. The combination of the two
225 is unique over a relatively long period of time - at least days.
226 Notifications from clients are sent with queue id 0, which will never be
227 used by the central authority.
228 '''),
229  6: (pyFrame, 'PKTDATA', 'Encapsulated packet data',
230 '''This frame format is normally used for a CDP or LLDP packet.
231 The data is kept exactly as it was received from the
232 network interface via libpcap.
233 '''),
234  7: (pyIntFrame, 'WALLCLOCK', '64-bit local time',
235 '''This frame provides local time on the sending system as gotten from the
236 g_get_real_time() call - which is a 64-bit time measured in microseconds.
237 In spite of the apparent variability permitted above, it is an 8-byte (64-bit) integer.
238 '''),
239  8: (pyCstringFrame, 'INTERFACE', 'Name of network interface as a C-style string',
240 '''This frame provides the name of a network interface as a
241 NUL-terminated C-style string.
242 '''),
243  9: (pyCstringFrame, 'HOSTNAME', 'Name of host as a C-style string',
244 '''This frame provides the name of a host as a NUL-terminated C-style string.
245 '''),
246  10: (pyAddrFrame, 'IPADDR', 'IP address in either IPv4 or IPv6 format.',
247 '''IPv4 addresses are address type 1 and are 4 bytes long.
248 IPv6 addresses are address type 2 and are 16 bytes long,
249 and have Address types 1 and 2 respectively.
250 '''),
251  11: (pyAddrFrame, 'MACADDR', 'MAC Address.',
252 '''This frame can be either a 6 byte (EUI-48) or an 8 byte (EUI-64) format MAC address.
253 The Address Type for a MAC address is 6.
254 '''),
255  12: (pyIntFrame, 'PORTNUM', 'Port number.',
256 '''This frame is a 16-bit IP port number.
257 '''),
258  13: (pyIpPortFrame, 'IPPORT', 'IP w/Port.',
259 '''This frame is a 16-bit IP port number along with an IPv4 or IPv6 address.
260 '''),
261  14: (pyIntFrame, 'HBINTERVAL', 'Heartbeat interval.',
262 '''This frame is a heartbeat sending interval measured in seconds.
263 '''),
264  15: (pyIntFrame, 'HBDEADTIME', 'Heartbeat deadtime.',
265 '''This frame is a heartbeat deadtime measured in seconds.
266 '''),
267  16: (pyIntFrame, 'HBWARNTIME', 'Heartbeat warntime.',
268 '''This frame is a heartbeat warning time measured in seconds.
269 '''),
270  17: (pyCstringFrame, 'PATHNAME', 'file name',
271 '''This frame contains a pathname for a file as a C string.
272 '''),
273  19: (pyCstringFrame, 'JSDISCOVER', 'JSON-formatted discovery data',
274 '''This frame contains JSON-formatted output from a discovery process.
275 The type of discovery data and program collecting it are inside.
276 '''),
277  20: (pyCstringFrame, 'CONFIGJSON', 'JSON configuration data from CMA',
278 'This frame provides the JSON for initial configuration data as a NUL-terminated C-style string.'),
279  21: (pyCstringFrame, 'CSTRINGVAL', 'Generic string value',
280 'Miscellaneous NUL-terminated C-style string.'),
281  22: (pyIntFrame, 'CINTVAL', 'Generic integer value',
282 'Miscellaneous integer value.'),
283  23: (pyIntFrame, 'ELAPSEDTIME', '64-bit elapsed time (usec)',
284 '''This frame provides elapsed time (measured locally) in microseconds.
285 In spite of the apparent variability permitted, it is an 8-byte (64-bit) integer.
286 '''),
287  24: (pyCstringFrame, 'DISCNAME', 'name of this discovery action',
288 '''This frame is a name to give this instance of a discovery action.
289 '''),
290  25: (pyIntFrame, 'DISCINTERVAL', 'Discovery interval',
291 '''This frame is a discovery repeat interval measured in seconds as an @ref IntFrame.
292 '''),
293  26: (pyCstringFrame, 'DISCJSON', 'Discovery JSON string',
294 '''This frame provides the data describing the discovery action in detail.
295  It must be preceded by a FRAMETYPE_DISCNAME.
296 '''),
297  27: (pyCstringFrame, 'RSCJSON', 'JSON resource string',
298 '''This frame provides the data describing the a resource action or cancel operation in detail.
299 '''),
300  28: (pyCstringFrame, 'RSCJSONREPLY', 'JSON operation result',
301 '''This frame provides the data describing the result of a resource action in detail.
302 '''),
303 
304  }
305  strframetypes = dict()
306  for i in intframetypes.keys():
307  data = intframetypes[i]
308  key = data[1]
309  strframetypes[key] = (i, data[0], key, data[1], data[2])
310 
311  def __init__(self):
312  pass
313  @staticmethod
314  def get(key):
315  'Return the tuple that corresponds to this key (integer or string)'
316  if type(key) is str:
317  return FrameTypes.strframetypes[key]
318  else:
319  if FrameTypes.intframetypes.has_key(int(key)):
320  return FrameTypes.intframetypes[int(key)]
321  return (None, str(key), str(key), str(key))
322 
323  @classmethod
324  def c_defines(cls, f):
325  'Generate C #defines from our data'
326  l = FrameTypes.intframetypes.keys()
327  l.sort()
328  f.write(FrameTypes.fileheader % __file__)
329  # Create pretty ASCII art pictures and #defines of all our different packet formats
330  for i in l:
331  ourtuple = FrameTypes.intframetypes[i]
332  pyclass = ourtuple[0].__name__
333  frametype = i
334  framename = ourtuple[1]
335  #framedesc = ourtuple[1]
336  frametext = ourtuple[3]
337  Cclassname = re.sub('^py', '', pyclass)
338  f.write('/**\n FRAMETYPE_%s Frame (<b>frametype %d</b>)'
339  ' Frame subclass - @ref %s\n' % (framename, frametype, Cclassname))
340  f.write('<PRE>%s</PRE>\n%s\n */\n' % (FrameTypes.asciiart[pyclass] % i, frametext))
341  f.write('#define FRAMETYPE_%s\t%d\t///< %s: @ref %s\n'
342  % (ourtuple[1], i, ourtuple[2], Cclassname))
343  f.write('///@}\n')
344  f.write('///@}\n')
345 
346  # Create the frame type map - mapping frame types to function names in the 'C' code.
347  f.write('#define FRAMETYPEMAP {\t\t\t\t\t\\\n')
348  for i in l:
349  tup = FrameTypes.intframetypes[i]
350  clsname = tup[0].__name__
351  Cclassname = re.sub('^py', '', clsname) + '_tlvconstructor'
352  Cfuncname = Cclassname.lower()
353  f.write(' {FRAMETYPE_%s,\t/*%d*/ %s}, \\\n' % (tup[1], i, Cfuncname))
354  f.write('}\n')
355 # Create conventional class.DEFINENAME attributes
356 for s in FrameTypes.strframetypes.keys():
357  setattr(FrameTypes, s, FrameTypes.strframetypes[s][0])
358 
360  'Class defining the universe of FrameSets - including code to generate a C header file'
361  _fileheader = \
362 '''#ifndef _FRAMESETTYPES_H
363 #define _FRAMESETTYPES_H
364 /**
365  * @file
366  * @brief Header file defining all known FrameSet types
367  * THIS FILE MECHANICALLY GENERATED by "%s". DO NOT EDIT.
368  *
369  * This file is part of the Assimilation Project.
370  *
371  * @author Copyright &copy; 2011, 2012 - Alan Robertson <alanr@unix.sh>
372  * @n
373  * The Assimilation software is free software: you can redistribute it and/or modify
374  * it under the terms of the GNU General Public License as published by
375  * the Free Software Foundation, either version 3 of the License, or
376  * (at your option) any later version.
377  *
378  * The Assimilation software is distributed in the hope that it will be useful,
379  * but WITHOUT ANY WARRANTY; without even the implied warranty of
380  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
381  * GNU General Public License for more details.
382  *
383  * You should have received a copy of the GNU General Public License
384  * along with the Assimilation Project software. If not, see http://www.gnu.org/licenses/
385  */
386 
387 /**
388  * @defgroup FrameSetTypes FrameSet Types
389  *
390  * @{
391  * @ingroup DefineEnums
392  */
393 '''
394  strframetypes = {
395  # nanoprobe peer-peer FrameSets
396  'HEARTBEAT': (1, 'A heartbeat packet'),
397  'PING': (2, 'Are you alive? (can also come from the CMA)'),
398  'PONG': (3, 'I am alive (can also go to the CMA)'),
399  # nanoprobe FrameSets sent to collective management authority
400  'ACK': (16, 'Frame referred to has been acted on. (can also come from the CMA)'),
401  'CONNSHUT': (17, 'Shutting down this connection (can also come from CMA)'),
402  'CONNNAK': (18, 'Ignoring your connection start request (can also come from CMA)'),
403 
404  'STARTUP': (25, 'System originating packet looking for heartbeat configuration.'),
405  'HBDEAD': (26, 'System named in packet appears to be dead.'),
406  'HBSHUTDOWN': (27, 'System originating packet has shut down.'),
407  'HBLATE': (28, 'System named in packet sent a late heartbeat.'),
408  'HBBACKALIVE': (29, 'System named in packet sent heartbeat after being marked dead.'),
409  'HBMARTIAN': (30, 'System named in packet appears gave unexpected heartbeat.'),
410  'SWDISCOVER': (31, 'Packet encapsulates switch discovery packet'),
411  'JSDISCOVERY': (32, 'Packet contains JSON-formatted discovery data'),
412  'RSCOPREPLY': (33, 'Packet contains return result from a resource operation'),
413  # 'Privileged' FrameSets sent from the CMA to nanoprobes
414  'SENDHB': (64, 'Send Heartbeats to these addresses'),
415  'EXPECTHB': (65, 'Expect (listen for) Heartbeats from these addresses'),
416  'SENDEXPECTHB': (66, 'Send Heartbeats to these addresses, and expect them as well.'),
417  'STOPSENDHB': (67, 'Stop sending Heartbeats to these addresses'),
418  'STOPEXPECTHB': (68, 'Stop expecting (listening for) Heartbeats from these addresses'),
419  'STOPSENDEXPECTHB':(69, 'Stop sending Heartbeats to these addresses'
420  ', and stop expecting them as well.'),
421  'SETCONFIG': (70, 'Initial configuration packet'),
422  'INCRDEBUG': (71, 'Increment debug for some or all classes'),
423  'DECRDEBUG': (72, 'Increment debug for some or all classes'),
424  'DODISCOVER': (73, 'Perform (repeating) JSON discovery action'),
425  'STOPDISCOVER': (74, 'Stop a repeating JSON discovery action'),
426  'DORSCOP': (75, 'Do a (possibly-repeating) JSON resource action'),
427  'STOPRSCOP': (76, 'Stop a (possibly-repeating) JSON resource action'),
428  'RUNSCRIPT': (76, 'Run an arbitrary script (not yet implemented)'),
429  }
430  intframetypes = dict()
431  for s in strframetypes.keys():
432  i = strframetypes[s][0]
433  intframetypes[i] = (s, strframetypes[s][1])
434 
435  def __init__(self):
436  pass
437 
438  @staticmethod
439  def get(key):
440  'Return the tuple that corresponds to this key (integer or string)'
441  if type(key) is str:
442  return FrameSetTypes.strframetypes[key]
443  else:
444  if FrameSetTypes.intframetypes.has_key(int(key)):
445  return FrameSetTypes.intframetypes[int(key)]
446  return (None, str(int(key)), str(int(key)), str(int(key)))
447 
448  @classmethod
449  def c_defines(cls, f):
450  'Print out the C #defines that go with this set of definitions'
451  f.write(FrameSetTypes._fileheader % __file__)
452  l = FrameSetTypes.intframetypes.keys()
453  l.sort()
454  for i in l:
455  ourtuple = FrameSetTypes.intframetypes[i]
456  f.write('#define FRAMESETTYPE_%s\t%d\t///< %s\n' % (ourtuple[0], i, ourtuple[1]))
457  f.write('///@}\n')
458  # Don't currently want this map - probably not needed (or even a good idea...)
459  #f.write('\n#define FRAMESETTYPEMAP {\t\t\t\t\t\t\\\n')
460  #for i in l:
461  #tup = FrameSetTypes.intframetypes[i]
462  #Cobjname = "frameset_listener_" + tup[0].lower()
463  #f.write(' {FRAMESETTYPE_%s,\t/*%d*/ %s}, \\\n' % (tup[0], i, Cobjname))
464  #f.write('}\n')
465 
466  f.write('#endif /* _FRAMESETTYPES_H */\n')
467 
468 # Create conventional class.DEFINENAME attributes
469 for s in FrameSetTypes.strframetypes.keys():
470  setattr(FrameSetTypes, s, FrameSetTypes.strframetypes[s][0])
471 
472 
473 if __name__ == "__main__":
474  import sys
475  if len(sys.argv) != 3 \
476  or ( sys.argv[1] != "frametypes" and sys.argv[1] != "framesettypes"):
477  sys.stderr.write("Usage: python %s (frametypes|framesettypes) output-filename\n"
478  % sys.argv[0])
479  raise SystemExit(1)
480  fvar = open(sys.argv[2], 'w')
481  if sys.argv[1] == "frametypes":
482  FrameTypes.c_defines(fvar)
483  sys.exit(0)
484  elif sys.argv[1] == "framesettypes":
485  FrameSetTypes.c_defines(fvar)
486  sys.exit(0)
487  raise SystemExit(1)