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