• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1% Real-Time Publish-Subscribe Protocol (RTPS) dissection
2%
3% Copyright (C) 2021 Trend Micro Incorporated
4% Copyright (C) 2021 Alias Robotics S.L.
5%
6% This program is free software; you can redistribute it and/or modify it under
7% the terms of the GNU General Public License as published by the Free Software
8% Foundation; either version 2 of the License, or (at your option) any later
9% version.
10%
11% This program is distributed in the hope that it will be useful, but WITHOUT ANY
12% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13% PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14%
15% You should have received a copy of the GNU General Public License along with
16% this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
17% Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
19% RTPS layer test campaign
20
21+ Syntax check
22= Import the RTPS layer
23from scapy.contrib.rtps import *
24pkt = b"\x52\x54\x50\x53\x02\x01\x01\x10\x57\x63\x10\x01\xd6\xab\x40\x7f" \
25      b"\x5b\xd9\xbb\x1c\x0e\x01\x0c\x00\x88\x2a\x10\x01\x5d\x8c\x97\x40" \
26      b"\x78\xb6\x2d\xc2\x09\x01\x08\x00\xf4\x50\x81\x60\x51\xdd\x5c\x1c" \
27      b"\x15\x05\x10\x01\x00\x00\x10\x00\x00\x01\x00\xc7\x00\x01\x00\xc2" \
28      b"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x03\x00\x00\x15\x00\x04\x00" \
29      b"\x02\x01\x00\x00\x16\x00\x04\x00\x01\x10\x00\x00\x02\x00\x08\x00" \
30      b"\x0a\x00\x00\x00\x00\x00\x00\x00\x50\x00\x10\x00\x57\x63\x10\x01" \
31      b"\xd6\xab\x40\x7f\x5b\xd9\xbb\x1c\x00\x00\x01\xc1\x58\x00\x04\x00" \
32      b"\x3f\x0c\x00\x00\x0f\x00\x04\x00\x00\x00\x00\x00\x31\x00\x18\x00" \
33      b"\x01\x00\x00\x00\xbd\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
34      b"\x00\x00\x00\x00\xac\x11\x00\x02\x48\x00\x18\x00\x01\x00\x00\x00" \
35      b"\xe9\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
36      b"\xef\xff\x00\x01\x32\x00\x18\x00\x01\x00\x00\x00\xbd\xeb\x00\x00" \
37      b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\x11\x00\x02" \
38      b"\x33\x00\x18\x00\x01\x00\x00\x00\xe8\x1c\x00\x00\x00\x00\x00\x00" \
39      b"\x00\x00\x00\x00\x00\x00\x00\x00\xef\xff\x00\x01\x07\x80\x38\x00" \
40      b"\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
41      b"\x00\x00\x00\x00\x1d\x00\x00\x00\x74\x65\x73\x74\x2e\x6c\x6f\x63" \
42      b"\x61\x6c\x2f\x30\x2e\x38\x2e\x30\x2f\x4c\x69\x6e\x75\x78\x2f\x4c" \
43      b"\x69\x6e\x75\x78\x00\x00\x00\x00\x19\x80\x04\x00\x00\x80\x06\x00" \
44      b"\x01\x00\x00\x00"
45
46+ Test endianness
47= PID_BUILTIN_ENDPOINT_QOS endianness
48assert raw(PID_BUILTIN_ENDPOINT_QOS(parameterId=119, parameterLength=0, parameterData=b"")) == b'w\x00\x00\x00'
49
50
51+ Test RTPS
52= RTPS default header values
53pkt2 = RTPS()/RTPSMessage(submessages=[
54    RTPSSubMessage_HEARTBEAT(),
55    RTPSSubMessage_INFO_TS(),
56    RTPSSubMessage_DATA(),
57])
58assert bytes(RTPS()) == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
59
60= RTPS packet declaration
61pkt3 = RTPS(
62    protocolVersion=ProtocolVersionPacket(major=2, minor=1),
63    vendorId=VendorIdPacket(vendor_id=0x0110),
64    guidPrefix=GUIDPrefixPacket(
65        hostId=1466109953, appId=3601547391, instanceId=1540995868
66    ),
67    magic=b"RTPS",
68) / RTPSMessage(
69    submessages=[
70        RTPSSubMessage_INFO_DST(
71            submessageId=14,
72            submessageFlags=1,
73            octetsToNextHeader=12,
74            guidPrefix=GUIDPrefixPacket(
75                hostId=2284457985, appId=1569494848, instanceId=2025205186
76            ),
77        ),
78        RTPSSubMessage_INFO_TS(
79            submessageId=9,
80            submessageFlags=1,
81            octetsToNextHeader=8,
82            ts_seconds=1619087604,
83            ts_fraction=475848017,
84        ),
85        RTPSSubMessage_DATA(
86            submessageId=21,
87            submessageFlags=5,
88            octetsToNextHeader=272,
89            extraFlags=0,
90            octetsToInlineQoS=16,
91            readerEntityIdKey=256,
92            readerEntityIdKind=199,
93            writerEntityIdKey=256,
94            writerEntityIdKind=194,
95            writerSeqNumHi=0,
96            writerSeqNumLow=1,
97            data=DataPacket(
98                encapsulationKind=3,
99                encapsulationOptions=0,
100                parameterList=ParameterListPacket(
101                    parameterValues=[
102                        PID_PROTOCOL_VERSION(
103                            parameterId=21,
104                            parameterLength=4,
105                            protocolVersion=ProtocolVersionPacket(major=2, minor=1),
106                            padding=b"\x00\x00",
107                        ),
108                        PID_VENDOR_ID(
109                            parameterId=22,
110                            parameterLength=4,
111                            vendorId=VendorIdPacket(vendor_id=0x0110),
112                            padding=b"\x00\x00",
113                        ),
114                        PID_PARTICIPANT_LEASE_DURATION(
115                            parameterId=2,
116                            parameterLength=8,
117                            parameterData=b"\n\x00\x00\x00\x00\x00\x00\x00",
118                        ),
119                        PID_PARTICIPANT_GUID(
120                            parameterId=80,
121                            parameterLength=16,
122                            guid=GUIDPacket(
123                                hostId=1466109953,
124                                appId=3601547391,
125                                instanceId=1540995868,
126                                entityId=449,
127                            ),
128                        ),
129                        PID_BUILTIN_ENDPOINT_SET(
130                            parameterId=88,
131                            parameterLength=4,
132                            parameterData=b"?\x0c\x00\x00",
133                        ),
134                        PID_DOMAIN_ID(
135                            parameterId=15,
136                            parameterLength=4,
137                            parameterData=b"\x00\x00\x00\x00",
138                        ),
139                        PID_DEFAULT_UNICAST_LOCATOR(
140                            parameterId=49,
141                            parameterLength=24,
142                            locator=LocatorPacket(
143                                locatorKind=1, port=60349, address="172.17.0.2"
144                            ),
145                        ),
146                        PID_DEFAULT_MULTICAST_LOCATOR(
147                            parameterId=72,
148                            parameterLength=24,
149                            locator=LocatorPacket(
150                                locatorKind=1, port=7401, address="239.255.0.1"
151                            ),
152                        ),
153                        PID_METATRAFFIC_UNICAST_LOCATOR(
154                            parameterId=50,
155                            parameterLength=24,
156                            locator=LocatorPacket(
157                                locatorKind=1, port=60349, address="172.17.0.2"
158                            ),
159                        ),
160                        PID_METATRAFFIC_MULTICAST_LOCATOR(
161                            parameterId=51,
162                            parameterLength=24,
163                            locator=LocatorPacket(
164                                locatorKind=1, port=7400, address="239.255.0.1"
165                            ),
166                        ),
167                        PID_UNKNOWN(
168                            parameterId=32775,
169                            parameterLength=56,
170                            parameterData=b"\x00\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00test.local/0.8.0/Linux/Linux\x00\x00\x00\x00",
171                        ),
172                        PID_UNKNOWN(
173                            parameterId=32793,
174                            parameterLength=4,
175                            parameterData=b"\x00\x80\x06\x00",
176                        ),
177                    ],
178                    sentinel=PID_SENTINEL(parameterId=1, parameterLength=0),
179                ),
180            ),
181        ),
182    ]
183)
184
185= RTPS header dissect
186assert pkt3.build() == pkt
187
188+ Test RTI RTPS
189= Test dissection
190d = b"\x52\x54\x50\x53\x02\x03\x01\x01\x01\x01\x30\xba\xa8\x7b\x1d\xce" \
191    b"\xb3\x29\x1e\x43\x09\x01\x08\x00\xd6\x64\xa8\x61\x16\x09\x34\x7c" \
192    b"\x15\x05\xdc\x02\x00\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\xc2" \
193    b"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x03\x00\x00\x50\x00\x10\x00" \
194    b"\x01\x01\x30\xba\xa8\x7b\x1d\xce\xb3\x29\x1e\x43\x00\x00\x01\xc1" \
195    b"\x58\x00\x04\x00\x3f\x0c\x00\x00\x77\x00\x04\x00\x01\x00\x00\x00" \
196    b"\x15\x00\x04\x00\x02\x03\x00\x00\x16\x00\x04\x00\x01\x01\x00\x00" \
197    b"\x00\x80\x04\x00\x06\x00\x01\x00\x59\x00\x78\x01\x06\x00\x00\x00" \
198    b"\x16\x00\x00\x00\x64\x64\x73\x2e\x73\x79\x73\x5f\x69\x6e\x66\x6f" \
199    b"\x2e\x68\x6f\x73\x74\x6e\x61\x6d\x65\x00\x00\x00\x0d\x00\x00\x00" \
200    b"\x64\x66\x30\x62\x36\x64\x38\x33\x61\x62\x34\x36\x00\x00\x00\x00" \
201    b"\x18\x00\x00\x00\x64\x64\x73\x2e\x73\x79\x73\x5f\x69\x6e\x66\x6f" \
202    b"\x2e\x70\x72\x6f\x63\x65\x73\x73\x5f\x69\x64\x00\x05\x00\x00\x00" \
203    b"\x34\x38\x33\x30\x00\x00\x00\x00\x21\x00\x00\x00\x64\x64\x73\x2e" \
204    b"\x73\x79\x73\x5f\x69\x6e\x66\x6f\x2e\x65\x78\x65\x63\x75\x74\x61" \
205    b"\x62\x6c\x65\x5f\x66\x69\x6c\x65\x70\x61\x74\x68\x00\x00\x00\x00" \
206    b"\x42\x00\x00\x00\x2f\x75\x73\x72\x2f\x6c\x6f\x63\x61\x6c\x2f\x73" \
207    b"\x72\x63\x2f\x72\x74\x69\x2f\x72\x65\x73\x6f\x75\x72\x63\x65\x2f" \
208    b"\x61\x70\x70\x2f\x62\x69\x6e\x2f\x78\x36\x34\x4c\x69\x6e\x75\x78" \
209    b"\x32\x2e\x36\x67\x63\x63\x34\x2e\x34\x2e\x35\x2f\x72\x74\x69\x64" \
210    b"\x64\x73\x73\x70\x79\x00\x00\x00\x14\x00\x00\x00\x64\x64\x73\x2e" \
211    b"\x73\x79\x73\x5f\x69\x6e\x66\x6f\x2e\x74\x61\x72\x67\x65\x74\x00" \
212    b"\x14\x00\x00\x00\x78\x36\x34\x4c\x69\x6e\x75\x78\x32\x2e\x36\x67" \
213    b"\x63\x63\x34\x2e\x34\x2e\x35\x00\x20\x00\x00\x00\x64\x64\x73\x2e" \
214    b"\x73\x79\x73\x5f\x69\x6e\x66\x6f\x2e\x63\x72\x65\x61\x74\x69\x6f" \
215    b"\x6e\x5f\x74\x69\x6d\x65\x73\x74\x61\x6d\x70\x00\x14\x00\x00\x00" \
216    b"\x32\x30\x32\x31\x2d\x30\x36\x2d\x37\x20\x30\x34\x3a\x30\x39\x3a" \
217    b"\x30\x32\x5a\x00\x21\x00\x00\x00\x64\x64\x73\x2e\x73\x79\x73\x5f" \
218    b"\x69\x6e\x66\x6f\x2e\x65\x78\x65\x63\x75\x74\x69\x6f\x6e\x5f\x74" \
219    b"\x69\x6d\x65\x73\x74\x61\x6d\x70\x00\x00\x00\x00\x14\x00\x00\x00" \
220    b"\x32\x30\x32\x31\x2d\x31\x32\x2d\x31\x20\x30\x39\x3a\x31\x35\x3a" \
221    b"\x32\x39\x5a\x00\x31\x00\x18\x00\x01\x00\x00\x00\xf3\x1c\x00\x00" \
222    b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
223    b"\x31\x00\x18\x00\x00\x00\x00\x01\xf3\x1c\x00\x00\x61\xab\xd9\x79" \
224    b"\xb5\x7c\x13\xa5\x29\x49\x2c\xa3\x00\x00\x00\x00\x32\x00\x18\x00" \
225    b"\x01\x00\x00\x00\xf2\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
226    b"\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x18\x00\x00\x00\x00\x01" \
227    b"\xf2\x1c\x00\x00\x61\xab\xd9\x79\xb5\x7c\x13\xa5\x29\x49\x2c\xa3" \
228    b"\x00\x00\x00\x00\x33\x00\x18\x00\x01\x00\x00\x00\xe8\x1c\x00\x00" \
229    b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xef\xff\x00\x01" \
230    b"\x02\x00\x08\x00\x06\x00\x00\x00\xff\xff\xff\x7f\x01\x80\x04\x00" \
231    b"\xff\xff\x00\x00\x62\x00\x28\x00\x22\x00\x00\x00\x52\x54\x49\x20" \
232    b"\x44\x61\x74\x61\x20\x44\x69\x73\x74\x72\x69\x62\x75\x74\x69\x6f" \
233    b"\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x20\x53\x70\x79\x00\x00\x00" \
234    b"\x0f\x00\x04\x00\x00\x00\x00\x00\x0f\x80\x04\x00\x00\x00\x00\x00" \
235    b"\x10\x80\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\xe3\xff\x00\x00" \
236    b"\x00\x00\x00\x01\x00\x00\x01\x00\x16\x80\x08\x00\x10\x00\x00\x00" \
237    b"\x00\x00\x00\x00\x17\x80\x04\x00\x03\x00\x00\x00\x01\x00\x00\x00"
238
239p0 = RTPS(d)
240p1 = RTPS(
241    protocolVersion=ProtocolVersionPacket(major=2, minor=3),
242    vendorId=VendorIdPacket(vendor_id=0x0101),
243    guidPrefix=GUIDPrefixPacket(
244        hostId=16855226, appId=2826640846, instanceId=3005816387
245    ),
246    magic=b"RTPS",
247) / RTPSMessage(
248    submessages=[
249        RTPSSubMessage_INFO_TS(
250            submessageId=9,
251            submessageFlags=1,
252            octetsToNextHeader=8,
253            ts_seconds=1638425814,
254            ts_fraction=2083784982,
255        ),
256        RTPSSubMessage_DATA(
257            submessageId=21,
258            submessageFlags=5,
259            octetsToNextHeader=732,
260            extraFlags=0,
261            octetsToInlineQoS=16,
262            readerEntityIdKey=0,
263            readerEntityIdKind=0,
264            writerEntityIdKey=256,
265            writerEntityIdKind=194,
266            writerSeqNumHi=0,
267            writerSeqNumLow=1,
268            data=DataPacket(
269                encapsulationKind=3,
270                encapsulationOptions=0,
271                parameterList=ParameterListPacket(
272                    parameterValues=[
273                        PID_PARTICIPANT_GUID(
274                            parameterId=80,
275                            parameterLength=16,
276                            guid=GUIDPacket(
277                                hostId=16855226,
278                                appId=2826640846,
279                                instanceId=3005816387,
280                                entityId=449,
281                            ),
282                        ),
283                        PID_BUILTIN_ENDPOINT_SET(
284                            parameterId=88,
285                            parameterLength=4,
286                            parameterData=b"?\x0c\x00\x00",
287                        ),
288                        PID_BUILTIN_ENDPOINT_QOS(
289                            parameterId=119,
290                            parameterLength=4,
291                            parameterData=b"\x01\x00\x00\x00",
292                        ),
293                        PID_PROTOCOL_VERSION(
294                            parameterId=21,
295                            parameterLength=4,
296                            protocolVersion=ProtocolVersionPacket(major=2, minor=3),
297                            padding=b"\x00\x00",
298                        ),
299                        PID_VENDOR_ID(
300                            parameterId=22,
301                            parameterLength=4,
302                            vendorId=VendorIdPacket(vendor_id=0x0101),
303                            padding=b"\x00\x00",
304                        ),
305                        PID_PRODUCT_VERSION(
306                            parameterId=32768,
307                            parameterLength=4,
308                            productVersion=ProductVersionPacket(
309                                major=6, minor=0, release=1, revision=0
310                            ),
311                        ),
312                        PID_PROPERTY_LIST(
313                            parameterId=89,
314                            parameterLength=376,
315                            parameterData=b"\x06\x00\x00\x00\x16\x00\x00\x00dds.sys_info.hostname\x00\x00\x00\r\x00\x00\x00df0b6d83ab46\x00\x00\x00\x00\x18\x00\x00\x00dds.sys_info.process_id\x00\x05\x00\x00\x004830\x00\x00\x00\x00!\x00\x00\x00dds.sys_info.executable_filepath\x00\x00\x00\x00B\x00\x00\x00/usr/local/src/rti/resource/app/bin/x64Linux2.6gcc4.4.5/rtiddsspy\x00\x00\x00\x14\x00\x00\x00dds.sys_info.target\x00\x14\x00\x00\x00x64Linux2.6gcc4.4.5\x00 \x00\x00\x00dds.sys_info.creation_timestamp\x00\x14\x00\x00\x002021-06-7 04:09:02Z\x00!\x00\x00\x00dds.sys_info.execution_timestamp\x00\x00\x00\x00\x14\x00\x00\x002021-12-1 09:15:29Z\x00",
316                        ),
317                        PID_DEFAULT_UNICAST_LOCATOR(
318                            parameterId=49,
319                            parameterLength=24,
320                            locator=LocatorPacket(
321                                locatorKind=1, port=7411, address="0.0.0.0"
322                            ),
323                        ),
324                        PID_DEFAULT_UNICAST_LOCATOR(
325                            parameterId=49,
326                            parameterLength=24,
327                            locator=LocatorPacket(
328                                locatorKind=16777216,
329                                port=7411,
330                                hostId=b"a\xab\xd9y\xb5|\x13\xa5)I,\xa3\x00\x00\x00\x00",
331                            ),
332                        ),
333                        PID_METATRAFFIC_UNICAST_LOCATOR(
334                            parameterId=50,
335                            parameterLength=24,
336                            locator=LocatorPacket(
337                                locatorKind=1, port=7410, address="0.0.0.0"
338                            ),
339                        ),
340                        PID_METATRAFFIC_UNICAST_LOCATOR(
341                            parameterId=50,
342                            parameterLength=24,
343                            locator=LocatorPacket(
344                                locatorKind=16777216,
345                                port=7410,
346                                hostId=b"a\xab\xd9y\xb5|\x13\xa5)I,\xa3\x00\x00\x00\x00",
347                            ),
348                        ),
349                        PID_METATRAFFIC_MULTICAST_LOCATOR(
350                            parameterId=51,
351                            parameterLength=24,
352                            locator=LocatorPacket(
353                                locatorKind=1, port=7400, address="239.255.0.1"
354                            ),
355                        ),
356                        PID_PARTICIPANT_LEASE_DURATION(
357                            parameterId=2,
358                            parameterLength=8,
359                            parameterData=b"\x06\x00\x00\x00\xff\xff\xff\x7f",
360                        ),
361                        PID_PLUGIN_PROMISCUITY_KIND(
362                            parameterId=32769, parameterLength=4, promiscuityKind=65535
363                        ),
364                        PID_ENTITY_NAME(
365                            parameterId=98,
366                            parameterLength=40,
367                            parameterData=b'"\x00\x00\x00RTI Data Distribution Service Spy\x00\x00\x00',
368                        ),
369                        PID_DOMAIN_ID(
370                            parameterId=15,
371                            parameterLength=4,
372                            parameterData=b"\x00\x00\x00\x00",
373                        ),
374                        PID_RTI_DOMAIN_ID(
375                            parameterId=32783, parameterLength=4, domainId=0
376                        ),
377                        PID_TRANSPORT_INFO_LIST(
378                            transportInfo=[
379                                TransportInfoPacket(classID=1, messageSizeMax=65507),
380                                TransportInfoPacket(
381                                    classID=16777216, messageSizeMax=65536
382                                ),
383                            ],
384                            parameterId=32784,
385                            parameterLength=20,
386                            padding=b"\x02\x00\x00\x00",
387                        ),
388                        PID_REACHABILITY_LEASE_DURATION(
389                            parameterId=32790,
390                            parameterLength=8,
391                            lease_duration=LeaseDurationPacket(
392                                seconds=268435456, fraction=0
393                            ),
394                        ),
395                        PID_VENDOR_BUILTIN_ENDPOINT_SET(
396                            parameterId=32791, parameterLength=4, flags=3
397                        ),
398                    ],
399                    sentinel=PID_SENTINEL(parameterId=1, parameterLength=0),
400                ),
401            ),
402        ),
403    ]
404)
405assert p0.build() == d
406assert p1.build() == d
407assert p1 == p0
408
409+ Test for pr #3914
410= RTPS Heartbeat SequenceNumber_t packing and dissection
411
412d = b"\x52\x54\x50\x53\x02\x02\x01\x0f\x01\x0f\x45\xd2\xb3\xf5\x58\xb9" \
413    b"\x01\x00\x00\x00\x07\x01\x1c\x00\x00\x00\x03\xc7\x00\x00\x03\xc2" \
414    b"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" \
415    b"\x01\x00\x00\x00"
416
417p0 = RTPS(d)
418
419p1 = RTPS(
420    protocolVersion=ProtocolVersionPacket(major=2, minor=2),
421    vendorId=VendorIdPacket(vendor_id=0x010f),
422    guidPrefix=GUIDPrefixPacket(
423        hostId=0x010f45d2, appId=0xb3f558b9, instanceId=0x01000000
424    ),
425    magic=b"RTPS",
426) / RTPSMessage(
427    submessages=[
428        RTPSSubMessage_HEARTBEAT(
429            submessageId=0x07,
430            submessageFlags=0x01,
431            octetsToNextHeader=28,
432            reader_id=b"\x00\x00\x03\xc7",
433            writer_id=b"\x00\x00\x03\xc2",
434            firstAvailableSeqNumHi=0,
435            firstAvailableSeqNumLow=1,
436            lastSeqNumHi=0,
437            lastSeqNumLow=1,
438            count=1
439        )
440    ]
441)
442
443assert p0.build() == d
444assert p1.build() == d
445assert p0 == p1
446
447+ Test for pr #3915
448= RTPS ACKNACK count packing and dissection
449
450d = b"\x52\x54\x50\x53\x02\x02\x01\x0f\x01\x0f\x45\xd2\xb3\xf5\x58\xb9" \
451    b"\x01\x00\x00\x00\x06\x03\x18\x00\x00\x00\x03\xc7\x00\x00\x03\xc2" \
452    b"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"
453p0 = RTPS(d)
454
455p1 = RTPS(
456    protocolVersion=ProtocolVersionPacket(major=2, minor=2),
457    vendorId=VendorIdPacket(vendor_id=0x010f),
458    guidPrefix=GUIDPrefixPacket(
459        hostId=0x010f45d2, appId=0xb3f558b9, instanceId=0x01000000
460    ),
461    magic=b"RTPS",
462) / RTPSMessage(
463    submessages=[
464        RTPSSubMessage_ACKNACK(
465            submessageId=6,
466            submessageFlags=3,
467            octetsToNextHeader=0x18,
468            reader_id=b'\x00\x00\x03\xc7',
469            writer_id=b'\x00\x00\x03\xc2',
470            readerSNState=b'\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00',
471            count=1
472        )
473    ]
474)
475
476assert p0.build() == d
477assert p1.build() == d
478assert p0 == p1
479