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