AcraNetwork 1.3.0__tar.gz → 1.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. acranetwork-1.3.2/AcraNetwork/GRE.py +24 -0
  2. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter24/__init__.py +4 -4
  3. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter7/Golay.py +21 -15
  4. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter7/golay_c.c +16 -10
  5. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/__version__.py +4 -1
  6. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork.egg-info/PKG-INFO +2 -1
  7. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork.egg-info/SOURCES.txt +5 -0
  8. {acranetwork-1.3.0 → acranetwork-1.3.2}/PKG-INFO +2 -1
  9. {acranetwork-1.3.0 → acranetwork-1.3.2}/README.md +2 -1
  10. acranetwork-1.3.2/examples/parse_mpeg_pcap.py +101 -0
  11. acranetwork-1.3.2/examples/pcap_to_ascii.py +114 -0
  12. acranetwork-1.3.2/examples/proxy_to_udp.py +95 -0
  13. acranetwork-1.3.2/examples/simple_mcast_capture.py +55 -0
  14. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_ch10.py +0 -7
  15. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_ch24.py +1 -1
  16. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_golay.py +213 -204
  17. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_simpleethernet.py +33 -5
  18. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IENA.py +0 -0
  19. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter10/Chapter10UDP.py +0 -0
  20. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter10/FileParser.py +0 -0
  21. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter10/__init__.py +0 -0
  22. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/ARINC429.py +0 -0
  23. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/Analog.py +0 -0
  24. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/CAN.py +0 -0
  25. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/ComputerData.py +0 -0
  26. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/MILSTD1553.py +0 -0
  27. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/PCM.py +0 -0
  28. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/TimeDataFormat.py +0 -0
  29. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/UART.py +0 -0
  30. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/Video.py +0 -0
  31. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter11/__init__.py +0 -0
  32. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/Chapter7/__init__.py +0 -0
  33. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/IRIG106/__init__.py +0 -0
  34. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/MPEG/ADTS.py +0 -0
  35. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/MPEG/H264.py +0 -0
  36. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/MPEG/PES.py +0 -0
  37. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/MPEG/PMT.py +0 -0
  38. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/MPEG/STANAG4609.py +0 -0
  39. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/MPEG/__init__.py +0 -0
  40. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/MPEGTS.py +0 -0
  41. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/McastSocket.py +0 -0
  42. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/NPD.py +0 -0
  43. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/ParserAligned.py +0 -0
  44. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/Pcap.py +0 -0
  45. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/SamDec008.py +0 -0
  46. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/SimpleEthernet.py +0 -0
  47. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/__init__.py +0 -0
  48. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/iNET.py +0 -0
  49. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/iNetX.py +0 -0
  50. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/nanotime.py +0 -0
  51. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork/ptptime.py +0 -0
  52. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork.egg-info/dependency_links.txt +0 -0
  53. {acranetwork-1.3.0 → acranetwork-1.3.2}/AcraNetwork.egg-info/top_level.txt +0 -0
  54. {acranetwork-1.3.0 → acranetwork-1.3.2}/LICENSE +0 -0
  55. {acranetwork-1.3.0 → acranetwork-1.3.2}/MANIFEST.in +0 -0
  56. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/adau_to_ch10.py +0 -0
  57. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/ch10_recorder.py +0 -0
  58. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/ch10_to_pcap.py +0 -0
  59. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/pkg_gen.ini +0 -0
  60. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/tx_iena_udp.py +0 -0
  61. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/tx_inetx_udp.py +0 -0
  62. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/validate_ch10.py +0 -0
  63. {acranetwork-1.3.0 → acranetwork-1.3.2}/examples/validate_pcap.py +0 -0
  64. {acranetwork-1.3.0 → acranetwork-1.3.2}/setup.cfg +0 -0
  65. {acranetwork-1.3.0 → acranetwork-1.3.2}/setup.py +0 -0
  66. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/__init__.py +0 -0
  67. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_afdx.py +0 -0
  68. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_ch7.py +0 -0
  69. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_iena.py +0 -0
  70. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_inet.py +0 -0
  71. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_inetx.py +0 -0
  72. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_misc.py +0 -0
  73. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_mpegts.py +0 -0
  74. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_npd.py +0 -0
  75. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_paligned.py +0 -0
  76. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_pcap.py +0 -0
  77. {acranetwork-1.3.0 → acranetwork-1.3.2}/test/test_ptptime.py +0 -0
@@ -0,0 +1,24 @@
1
+ import typing
2
+ import struct
3
+
4
+ GRE_MAX_SEQ = pow(2, 32)
5
+ GRE_TYPE_SECURE_DATA = 0x876D
6
+ GRE_TYPE_RESERVED = 0xFFFF
7
+
8
+
9
+ class GRE(object):
10
+ """
11
+ Generic Routing Encapsulation (GRE) defined in RFC1701
12
+ This implements a single variant of this only.
13
+ Sequence number supported and no other optional fiend
14
+ """
15
+
16
+ def __init__(self) -> None:
17
+ self.protocol_type: int = GRE_TYPE_RESERVED
18
+ self.sequence: int = 0
19
+ self.payload: typing.Optional[bytes] = None
20
+
21
+ def pack(self) -> bytes:
22
+ flags = 1 << 12
23
+ _hdr = struct.pack(">HHI", flags, self.protocol_type, self.sequence % GRE_MAX_SEQ)
24
+ return _hdr + self.payload
@@ -162,7 +162,7 @@ class TmNSMessage:
162
162
  >>> pkt = ch24.TmNSMessage()
163
163
  >>> pkt.flags.acquired = ch24.DataSourceAcquiredDataFlag.SIMULATED
164
164
  >>> pkt.flags.fragmentation = ch24.MessageFragmentationFlags.LASTFRAGMENT
165
- >>> pkt.defintionid = 0x1234
165
+ >>> pkt.definitionid = 0x1234
166
166
  >>> pkt.sequence = 100
167
167
  >>> pkt.payload = struct.pack(">HH", 0x1, 0x2)
168
168
  >>> b = pkt.pack()
@@ -173,7 +173,7 @@ class TmNSMessage:
173
173
  msgtype: int = TYPE_TMNS
174
174
  optionwordcount: int = 0
175
175
  version: int = VERSION
176
- defintionid: int = 0
176
+ definitionid: int = 0
177
177
  sequence: int = 0
178
178
  length: int = 0
179
179
  timestamp: int = 0
@@ -185,7 +185,7 @@ class TmNSMessage:
185
185
  Convert the byte buffer into a TmNSMessage object
186
186
  """
187
187
  self.flags.unpack(buffer[0:2])
188
- (_type, _ver_opt, self.defintionid, self.sequence, self.length, self.timestamp) = struct.unpack_from(
188
+ (_type, _ver_opt, self.definitionid, self.sequence, self.length, self.timestamp) = struct.unpack_from(
189
189
  TMNS_STRUCT, buffer, 2
190
190
  )
191
191
  self.msgtype = _type & 0xF
@@ -209,7 +209,7 @@ class TmNSMessage:
209
209
  TMNS_STRUCT,
210
210
  self.msgtype,
211
211
  self.optionwordcount + (self.version << 4),
212
- self.defintionid,
212
+ self.definitionid,
213
213
  self.sequence,
214
214
  self.length,
215
215
  self.timestamp,
@@ -20,12 +20,13 @@ from functools import lru_cache
20
20
  import warnings
21
21
 
22
22
  try:
23
- from . import golay_c as _golay_native
23
+ from . import golay_c as _golay_native # type: ignore
24
24
 
25
- _use_c_extension = True
25
+ _c_extension_available = True
26
26
  except ImportError:
27
27
  warnings.warn("C extension for Golay not found. Falling back to pure Python.", RuntimeWarning)
28
- _use_c_extension = False
28
+ _c_extension_available = False
29
+ _use_c_extension = _c_extension_available # default behavior, unchanged
29
30
 
30
31
 
31
32
  GOLAY_SIZE = 0x1000
@@ -47,14 +48,20 @@ class Golay:
47
48
  CorrectTable = None
48
49
  ErrorTable = None
49
50
 
50
- def __init__(self):
51
- if _use_c_extension:
51
+ def __init__(self, use_c_extension=None):
52
+ if use_c_extension:
53
+ use_c_extension = _use_c_extension
54
+ if use_c_extension and not _c_extension_available:
55
+ raise RuntimeError("C extension for Golay requested but not available")
56
+ self._use_c_extension = use_c_extension
57
+
58
+ if self._use_c_extension:
52
59
  _golay_native.golay_init_tables()
53
60
  else:
54
- if Golay.EncodeTable is None:
61
+ if Golay.EncodeTable is None:
55
62
  self._init_encode_table()
56
- self._initgolaydecode()
57
-
63
+ if Golay.SyndromeTable is None:
64
+ self._initgolaydecode()
58
65
 
59
66
  def _init_encode_table(self):
60
67
  Golay.EncodeTable = [0] * GOLAY_SIZE
@@ -68,7 +75,7 @@ class Golay:
68
75
  if not (0 <= raw <= 0xFFF):
69
76
  raise ValueError("Only 12-bit unsigned values allowed")
70
77
 
71
- if _use_c_extension:
78
+ if self._use_c_extension:
72
79
  encoded = _golay_native.golay_encode(raw)
73
80
  else:
74
81
  encoded = self._encode_python(raw)
@@ -78,7 +85,7 @@ class Golay:
78
85
  return encoded
79
86
 
80
87
  def decode(self, encoded):
81
- if _use_c_extension:
88
+ if self._use_c_extension:
82
89
  return _golay_native.golay_decode(encoded)
83
90
  else:
84
91
  # encoded is either an integer <= 0xFFFFFF, or is a bytes-like type
@@ -92,7 +99,6 @@ class Golay:
92
99
  v = encoded
93
100
  return self._decode_python(v)
94
101
 
95
-
96
102
  def _encode_python(self, raw):
97
103
  """
98
104
  Encode the value as a 24b code
@@ -104,7 +110,7 @@ class Golay:
104
110
  :param raw: value to be encoded that is already validated to be 0..FFF
105
111
  :return: encoded value as a 24-bit integer
106
112
  """
107
- # self.encode() has already checked that 0 <= raw <= 0xFFF so do not
113
+ # self.encode() has already checked that 0 <= raw <= 0xFFF so do not
108
114
  # check again
109
115
  # Also, there is no to_string argument because that is handled by
110
116
  # encode()
@@ -122,9 +128,9 @@ class Golay:
122
128
  :param v: integer that has already been validated to be 24bit
123
129
  :return: decoded 12-bit value
124
130
  """
125
- # self.decode() has converted the value to an integer and verified
131
+ # self.decode() has converted the value to an integer and verified
126
132
  # that it is valid. So do not repeat the check.
127
-
133
+
128
134
  return self._decode2(((v) >> 12) & 0xFFF, (v) & 0xFFF)
129
135
 
130
136
  def _syndrome2(self, v1, v2):
@@ -143,7 +149,7 @@ class Golay:
143
149
  return self._errors2(((v) >> 12) & 0xFFF, (v) & 0xFFF)
144
150
 
145
151
  def errors(self, v):
146
- if _use_c_extension:
152
+ if self._use_c_extension:
147
153
  return _golay_native.golay_errors(v)
148
154
  else:
149
155
  return self._errors(v)
@@ -52,7 +52,6 @@ static void InitGolayEncode(void)
52
52
  }
53
53
  }
54
54
 
55
- // Initialize the Golay decoding lookup tables
56
55
  static void InitGolayDecode(void)
57
56
  {
58
57
  for (uint32_t x = 0; x < GOLAY_SIZE; x++)
@@ -80,7 +79,7 @@ static void InitGolayDecode(void)
80
79
  for (int k = 0; k < 24; k++)
81
80
  {
82
81
  uint32_t error = (1 << i) | (1 << j) | (1 << k);
83
- uint16_t syndrome = SyndromeTable[(error >> 12) & 0x0FFF] ^ (error & 0x0FFF);
82
+ uint16_t syndrome = SyndromeTable[error & 0x0FFF] ^ ((error >> 12) & 0x0FFF);
84
83
  CorrectTable[syndrome] = (error >> 12) & 0x0FFF;
85
84
  ErrorTable[syndrome] = ones_in_code(error, 24);
86
85
  }
@@ -124,17 +123,24 @@ static PyObject *py_golay_decode(PyObject *self, PyObject *args)
124
123
 
125
124
  uint32_t encoded;
126
125
 
127
- // Handle bytes input (should be 3 bytes)
128
- if (PyBytes_Check(input))
126
+ // Handle bytes-like input (bytes, bytearray, memoryview, etc.)
127
+ if (PyObject_CheckBuffer(input))
129
128
  {
130
- if (PyBytes_Size(input) != 3)
129
+ Py_buffer view;
130
+ if (PyObject_GetBuffer(input, &view, PyBUF_SIMPLE) != 0)
131
131
  {
132
+ return NULL; // GetBuffer already sets an exception
133
+ }
134
+ if (view.len != 3)
135
+ {
136
+ PyBuffer_Release(&view);
132
137
  PyErr_SetString(PyExc_ValueError, "3-byte input required");
133
138
  return NULL;
134
139
  }
135
- const unsigned char *buf = (const unsigned char *)PyBytes_AsString(input);
140
+ const unsigned char *buf = (const unsigned char *)view.buf;
136
141
  // Convert big-endian bytes to 24-bit unsigned integer
137
142
  encoded = ((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | buf[2];
143
+ PyBuffer_Release(&view);
138
144
  }
139
145
  // Handle integer input
140
146
  else if (PyLong_Check(input))
@@ -142,21 +148,21 @@ static PyObject *py_golay_decode(PyObject *self, PyObject *args)
142
148
  encoded = PyLong_AsUnsignedLong(input);
143
149
  if (PyErr_Occurred())
144
150
  {
145
- return NULL; // Overflow or invalid conversion
151
+ return NULL;
146
152
  }
147
153
  if (encoded > 0xFFFFFF)
148
154
  {
149
- PyErr_SetString(PyExc_ValueError, "Input must be a 24-bit unsigned integer.");
155
+ PyErr_SetString(PyExc_ValueError, "Only 24-bit unsigned values supported");
150
156
  return NULL;
151
157
  }
152
158
  }
153
159
  else
154
160
  {
155
- PyErr_SetString(PyExc_TypeError, "Expected a 3-byte bytes object or 24-bit integer.");
161
+ PyErr_SetString(PyExc_TypeError, "Expected a bytes-like object (3 bytes) or 24-bit integer.");
156
162
  return NULL;
157
163
  }
158
164
 
159
- // Decode logic
165
+ // Decode logic unchanged
160
166
  uint16_t v1 = (encoded >> 12) & 0x0FFF;
161
167
  uint16_t v2 = encoded & 0x0FFF;
162
168
  uint16_t syndrome = SyndromeTable[v2] ^ v1;
@@ -118,4 +118,7 @@
118
118
  # - simplified Golay.py; removed some redundant checks
119
119
  # 1.2.9 - Added __init__.py back into the test folder to allow pytest to run
120
120
  # 1.3.0 - STart to add support for TmNSMessage
121
- __version__ = "1.3.0"
121
+ # 1.3.1 - Fixed typo in defintionid
122
+ # 1.3.2 - Aligned the C implementation of Golay with the python code. Unittest tests both C and Python. Performance improvements in python code
123
+
124
+ __version__ = "1.3.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AcraNetwork
3
- Version: 1.3.0
3
+ Version: 1.3.2
4
4
  Summary: Classes and utilities to support Flight Test Instrumentation Ethernet networks
5
5
  Home-page: https://github.com/diarmuidcwc/AcraNetwork
6
6
  Author: Diarmuid Collins
@@ -42,6 +42,7 @@ Full documentation is available here https://acranetwork.readthedocs.io/en/lates
42
42
  * MPEGTS: MpegTransport stream packets
43
43
 
44
44
 
45
+
45
46
  ## Install
46
47
 
47
48
  Install using pip
@@ -3,6 +3,7 @@ MANIFEST.in
3
3
  README.md
4
4
  setup.cfg
5
5
  setup.py
6
+ AcraNetwork/GRE.py
6
7
  AcraNetwork/IENA.py
7
8
  AcraNetwork/MPEGTS.py
8
9
  AcraNetwork/McastSocket.py
@@ -48,7 +49,11 @@ AcraNetwork/MPEG/__init__.py
48
49
  examples/adau_to_ch10.py
49
50
  examples/ch10_recorder.py
50
51
  examples/ch10_to_pcap.py
52
+ examples/parse_mpeg_pcap.py
53
+ examples/pcap_to_ascii.py
51
54
  examples/pkg_gen.ini
55
+ examples/proxy_to_udp.py
56
+ examples/simple_mcast_capture.py
52
57
  examples/tx_iena_udp.py
53
58
  examples/tx_inetx_udp.py
54
59
  examples/validate_ch10.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AcraNetwork
3
- Version: 1.3.0
3
+ Version: 1.3.2
4
4
  Summary: Classes and utilities to support Flight Test Instrumentation Ethernet networks
5
5
  Home-page: https://github.com/diarmuidcwc/AcraNetwork
6
6
  Author: Diarmuid Collins
@@ -42,6 +42,7 @@ Full documentation is available here https://acranetwork.readthedocs.io/en/lates
42
42
  * MPEGTS: MpegTransport stream packets
43
43
 
44
44
 
45
+
45
46
  ## Install
46
47
 
47
48
  Install using pip
@@ -23,6 +23,7 @@ Full documentation is available here https://acranetwork.readthedocs.io/en/lates
23
23
  * MPEGTS: MpegTransport stream packets
24
24
 
25
25
 
26
+
26
27
  ## Install
27
28
 
28
29
  Install using pip
@@ -58,4 +59,4 @@ pip install --upgrade pip wheel setuptools twine
58
59
  rm dist/*
59
60
  python ./setup.py sdist bdist_wheel --universal sdist
60
61
  twine upload dist/*
61
- ```
62
+ ```
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ =====
5
+ Parse MPEG TS packets in pcap....
6
+ =====
7
+
8
+ """
9
+ __author__ = "Diarmuid Collins"
10
+ __copyright__ = "Copyright 2018"
11
+ __version__ = "0.0.1"
12
+ __maintainer__ = "Diarmuid Collins"
13
+ __email__ = "dcollins@curtisswright.com"
14
+ __status__ = "Production"
15
+
16
+
17
+ import sys
18
+ sys.path.append("..")
19
+ import AcraNetwork.Pcap as pcap
20
+ import AcraNetwork.iNetX as inetx
21
+ import AcraNetwork.MPEGTS as mpegts
22
+ import AcraNetwork.SimpleEthernet as eth
23
+ from AcraNetwork.MPEGTS import H264
24
+ import datetime
25
+
26
+ # This script shows how to parse either a pcap file or a TS file into the constituent
27
+ # NALS and finds the unique STANAG SEI User data with the timestamp
28
+
29
+
30
+ def pcap_to_ts(pcapfile,ts_file,udp_port=8010):
31
+ '''
32
+ Convert a pcap file to a TS file by extracting all data from a specified port
33
+ :param mpegfile: str
34
+ :param ts_file: str
35
+ :param udp_port: int
36
+ :return:
37
+ '''
38
+
39
+ mpegpcap = pcap.Pcap(pcapfile, mode='r')
40
+
41
+ ts = open(ts_file, mode='wb')
42
+ mpeghex = ""
43
+ rec_count = 0
44
+
45
+ for rec in mpegpcap:
46
+ try:
47
+ e = eth.Ethernet()
48
+ e.unpack(rec.packet)
49
+ i = eth.IP()
50
+ i.unpack(e.payload)
51
+ u = eth.UDP()
52
+ u.unpack(i.payload)
53
+ if u.dstport == udp_port:
54
+ rec_count += 1
55
+ inet = inetx.iNetX()
56
+ inet.unpack(u.payload)
57
+ mpegtspackets = mpegts.MPEGTS()
58
+ mpegtspackets.unpack(inet.payload)
59
+ for packet in mpegtspackets.blocks:
60
+ mpeghex += packet.payload
61
+ ts.write(inet.payload)
62
+ except:
63
+ continue
64
+
65
+
66
+ def parse_ts_file(tsfile):
67
+
68
+ ts_file = open(tsfile,mode='rb')
69
+ h264_data = H264()
70
+ h264_data.unpack(ts_file.read())
71
+
72
+ nal_counts = {}
73
+ timestamp_count = 0
74
+ for nal in h264_data.nals:
75
+
76
+ if not nal.type in nal_counts:
77
+ nal_counts[nal.type] = 1
78
+ else:
79
+ nal_counts[nal.type] += 1
80
+
81
+ if nal.type == mpegts.NAL_TYPES["SEI"]:
82
+ if nal.sei.unregdata:
83
+ print("Timestamp={} byte offset={} count ={}".format(datetime.datetime.strftime(nal.sei.time,"%d %b %Y %H:%M:%S.%f"),nal.offset,timestamp_count))
84
+ timestamp_count += 1
85
+
86
+ else:
87
+ pass
88
+
89
+ print("\n----- SUMMARY -----")
90
+ for type in nal_counts:
91
+ print("{} {} NALs in input".format(nal_counts[type],mpegts.NAL_TYPES_INV[type]))
92
+ print("{} STANAG Timestamps".format(timestamp_count))
93
+
94
+
95
+ def main():
96
+ # Read in a TS file and print out some useful information
97
+ parse_ts_file("../test/stanag_sample.ts")
98
+
99
+
100
+ if __name__ == "__main__":
101
+ main()
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ =====
5
+ PCAP to ASCII
6
+ =====
7
+
8
+
9
+ """
10
+ __author__ = "Diarmuid Collins"
11
+ __copyright__ = "Copyright 2018"
12
+ __version__ = "0.0.1"
13
+ __maintainer__ = "Diarmuid Collins"
14
+ __email__ = "dcollins@curtisswright.com"
15
+ __status__ = "Production"
16
+
17
+
18
+ import sys
19
+ sys.path.append("..")
20
+
21
+ import os,struct
22
+ import argparse
23
+
24
+ import AcraNetwork.iNetX as inetx
25
+ import AcraNetwork.Pcap as pcap
26
+ import AcraNetwork.SimpleEthernet as SimpleEthernet
27
+
28
+
29
+ def main():
30
+
31
+ #----------------------------------
32
+ # Setup the command line parser
33
+ #----------------------------------
34
+ parser = argparse.ArgumentParser(description='Dump out the _payload of iNetX packets as ASCII representations')
35
+ parser.add_argument('--pcap', required=True, action='append', help='The input pcap file(s)')
36
+ parser.add_argument('--hex', required=False, action='store_true', default=False, help='Print the hex representation not the ASCII coded version')
37
+ parser.add_argument('--outdir', required=False, default="out", help='Name of output directory. Default is out')
38
+ args = parser.parse_args()
39
+
40
+ #------------------------------------------------------------
41
+ # Now read the input.
42
+ #------------------------------------------------------------
43
+ # The input will take multiple pcap files and loop through each
44
+
45
+ # Keep a track of the position in the line for each streamID
46
+ output_byte_count ={}
47
+
48
+ for pcapfilename in args.pcap:
49
+ try:
50
+ pcapfile = pcap.Pcap(pcapfilename)
51
+ except IOError:
52
+ print("ERROR: File {} not found".format(pcapfilename))
53
+ exit()
54
+
55
+ if not os.path.exists(args.outdir):
56
+ os.mkdir(args.outdir)
57
+
58
+ for pcaprecord in pcapfile:
59
+ eth = SimpleEthernet.Ethernet()
60
+ eth.unpack(pcaprecord.packet)
61
+ ip = SimpleEthernet.IP()
62
+ ip.unpack(eth.payload)
63
+ udp_packet = SimpleEthernet.UDP()
64
+ udp_packet.unpack(ip.payload)
65
+ (ctrl_word,) = struct.unpack('>I',udp_packet.payload[:4])
66
+
67
+ if ctrl_word == 0x11000000:
68
+ inetx_packet = inetx.iNetX()
69
+ # Unpack the udp _payload as an iNetx packet
70
+ inetx_packet.unpack(udp_packet.payload)
71
+ # Do we want to dump out an ascii or hex output
72
+ if args.hex == True:
73
+ prefix = "hex"
74
+ else:
75
+ prefix = "ascii"
76
+
77
+ # Create an output file per streamID and open it
78
+ output_file_name = "{}/{}_{:08X}.txt".format(args.outdir,prefix,inetx_packet.streamid)
79
+ # NB: We are appending to the file here so if you have existing files in the directory then it will be appended
80
+ output_file = open(output_file_name,'a')
81
+
82
+ # Start the byte count per streamID
83
+ if inetx_packet.streamid not in output_byte_count:
84
+ output_byte_count[inetx_packet.streamid] = 1
85
+
86
+ # Go thorough each byte in the _payload. Not particularly efficient
87
+ for offset in range(len(inetx_packet.payload)):
88
+ # Unpack the _payload as an unsigned integer
89
+ (byte_in_ascii,) =struct.unpack_from('B', inetx_packet.payload, offset)
90
+
91
+ # Write the output depending on what you want
92
+ if args.hex == True:
93
+ output_file.write("{:02X} ".format(byte_in_ascii))
94
+ else:
95
+ # Only some ASCII codes are printable so don't print out
96
+ # the non printable ones. Emulate the wireshark method of printing a period
97
+ if byte_in_ascii < 31 or byte_in_ascii > 126:
98
+ printable_string = "."
99
+ else:
100
+ printable_string = chr(byte_in_ascii)
101
+
102
+ output_file.write("{}".format(printable_string))
103
+
104
+ # Create a new line after 16 bytes for readability
105
+ if (output_byte_count[inetx_packet.streamid] % 16 == 0):
106
+ output_file.write('\n')
107
+ output_byte_count[inetx_packet.streamid] += 1
108
+
109
+ print("Output files created in {} directory".format(args.outdir))
110
+
111
+
112
+
113
+ if __name__ == '__main__':
114
+ main()
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ =====
5
+ Proxy iNetx or IENA packets to UDP
6
+ =====
7
+
8
+
9
+ """
10
+ __author__ = "Diarmuid Collins"
11
+ __copyright__ = "Copyright 2018"
12
+ __version__ = "0.1.0"
13
+ __maintainer__ = "Diarmuid Collins"
14
+ __email__ = "dcollins@curtisswright.com"
15
+ __status__ = "Production"
16
+
17
+
18
+ import sys
19
+ sys.path.append("..")
20
+ import socket
21
+ import argparse
22
+ import AcraNetwork.iNetX as inetx
23
+ import AcraNetwork.IENA as iena
24
+ import AcraNetwork.McastSocket as McastSocket
25
+
26
+ VERSION = __version__
27
+
28
+ parser = argparse.ArgumentParser(description='Proxy iNetX or IENA packets to UDP')
29
+ parser.add_argument('--ipaddress', type=str, default="235.0.0.1", required=True, help='The multicast IP address on which the iNetX or IENA packets are being transmitted')
30
+ parser.add_argument('--inetx', type=int, default=None, required=False, help='Receiving iNetX packets on this UDP port. Either this argument of --iena should be supplpied')
31
+ parser.add_argument('--iena', type=int, default=None, required=False, help='Receiving IENA packets on this UDP port')
32
+ parser.add_argument('--udp', type=int, default=None, required=True, help='Transmit UDP packets on this UDP port')
33
+ parser.add_argument('--version', action='version', version='%(prog)s {}'.format(VERSION))
34
+
35
+ args = parser.parse_args()
36
+
37
+ if not (args.inetx or args.iena):
38
+ print(parser.print_help())
39
+ sys.exit(1)
40
+
41
+ # The incoming iNetx port
42
+ if args.inetx:
43
+ incoming_udp_port = args.inetx
44
+ else:
45
+ incoming_udp_port = args.iena
46
+
47
+ # Outgoing UDP port
48
+ outgoing_udp_port = args.udp
49
+
50
+ #------------------------------------------------------------
51
+ # Setup a socket to recieve all traffic
52
+ #------------------------------------------------------------
53
+ try:
54
+ recv_socket = McastSocket.McastSocket(local_port=incoming_udp_port, reuse=1)
55
+ recv_socket.mcast_add(args.ipaddress, '0.0.0.0')
56
+ recv_socket.settimeout(10)
57
+ except:
58
+ print("Can't bind to socket {} on multicast {}".format(incoming_udp_port, args.ipaddress))
59
+ exit()
60
+
61
+ tx_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
62
+
63
+ packet_count = 1
64
+
65
+
66
+ while True:
67
+ # Capture some data
68
+ try:
69
+ data, addr = recv_socket.recvfrom(2048) # buffer size is 1500 bytes
70
+ except socket.timeout:
71
+ print("ERROR: No incoming packets received on UDP port {} on multicast {}. Timeout on socket".format(
72
+ incoming_udp_port, args.ipaddress))
73
+ exit()
74
+
75
+ (udpsrcport,srcipaddr) = addr
76
+ # Decode it as iNetx
77
+ if args.inetx:
78
+ avionics_packet = inetx.iNetX()
79
+ else:
80
+ avionics_packet = iena.IENA()
81
+
82
+ try:
83
+ avionics_packet.unpack(data)
84
+ except ValueError:
85
+ # This isn't an inetx packet
86
+ continue
87
+ else:
88
+ packet_count += 1
89
+ # Transmit the _payload back out
90
+ tx_socket.sendto(avionics_packet.payload, (args.ipaddress, outgoing_udp_port))
91
+ # Print some info for the user
92
+ if packet_count % 50 == 0:
93
+ print(".")
94
+ else:
95
+ print(".",)
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ =====
5
+ Multicast reception example
6
+ =====
7
+
8
+
9
+ """
10
+ __author__ = "Diarmuid Collins"
11
+ __copyright__ = "Copyright 2018"
12
+ __version__ = "0.1.0"
13
+ __maintainer__ = "Diarmuid Collins"
14
+ __email__ = "dcollins@curtisswright.com"
15
+ __status__ = "Production"
16
+
17
+ import sys
18
+ sys.path.append("..")
19
+
20
+ import socket
21
+ import AcraNetwork.iNetX as inetx
22
+ import AcraNetwork.McastSocket as McastSocket
23
+
24
+ udp_port = 5567
25
+
26
+ #------------------------------------------------------------
27
+ # Setup a socket to recieve all traffic
28
+ #------------------------------------------------------------
29
+ try:
30
+ recv_socket = McastSocket.McastSocket(local_port=udp_port, reuse=1)
31
+ recv_socket.mcast_add('235.0.0.1', '0.0.0.0')
32
+ recv_socket.settimeout(10)
33
+ except:
34
+ print("Can't bind to socket {}".format(udp_port))
35
+ exit()
36
+
37
+ packet_count = 1
38
+ while True:
39
+ try:
40
+ data, addr = recv_socket.recvfrom(2048) # buffer size is 1500 bytes
41
+ except socket.timeout:
42
+ print("timeout on socket")
43
+ exit()
44
+
45
+ (udpsrcport,srcipaddr) = addr
46
+ avionics_packet = inetx.iNetX()
47
+ data_len = len(data)
48
+ try:
49
+ avionics_packet.unpack(data)
50
+ except ValueError:
51
+ # This isn't an inetx packet
52
+ packet_count += 1
53
+ continue
54
+ else:
55
+ print("Packet withStread ID = {:0X}".format(avionics_packet.streamid))