ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
dds.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file dds.cpp
6 * @brief DDS / RTPS wire-protocol framing codec (see dds.h).
7 */
8
10
11#if PC_ENABLE_DDS
12
13#include <string.h>
14
15const uint8_t RTPS_VERSION[2] = {2, 4};
16
17size_t pc_rtps_header(const uint8_t *guid_prefix, const uint8_t *vendor_id, uint8_t *out, size_t cap)
18{
19 if (!guid_prefix || !vendor_id || !out || cap < Rtps::RTPS_HEADER_LEN)
20 {
21 return 0;
22 }
23 out[0] = 'R';
24 out[1] = 'T';
25 out[2] = 'P';
26 out[3] = 'S';
27 out[4] = RTPS_VERSION[0];
28 out[5] = RTPS_VERSION[1];
29 out[6] = vendor_id[0];
30 out[7] = vendor_id[1];
31 memcpy(out + 8, guid_prefix, Rtps::RTPS_GUIDPREFIX_LEN);
32 return Rtps::RTPS_HEADER_LEN;
33}
34
35size_t pc_rtps_submessage(uint8_t id, uint8_t flags, const uint8_t *body, uint16_t body_len, uint8_t *out, size_t cap)
36{
37 if (!out || (body_len && !body))
38 {
39 return 0;
40 }
41 size_t n = 4 + (size_t)body_len;
42 if (n > cap)
43 {
44 return 0;
45 }
46 out[0] = id;
47 out[1] = flags;
48 // octetsToNextHeader is written in the submessage's own byte order (the E flag).
49 if (flags & Rtps::RTPS_FLAG_ENDIAN)
50 {
51 out[2] = (uint8_t)body_len;
52 out[3] = (uint8_t)(body_len >> 8);
53 }
54 else
55 {
56 out[2] = (uint8_t)(body_len >> 8);
57 out[3] = (uint8_t)body_len;
58 }
59 if (body_len)
60 {
61 memcpy(out + 4, body, body_len);
62 }
63 return n;
64}
65
66bool pc_rtps_parse(const uint8_t *msg, size_t len, pc_rtps_cb cb, void *arg)
67{
68 if (!msg || len < Rtps::RTPS_HEADER_LEN)
69 {
70 return false;
71 }
72 if (msg[0] != 'R' || msg[1] != 'T' || msg[2] != 'P' || msg[3] != 'S')
73 {
74 return false;
75 }
76 // Accept any peer whose protocol version is <= ours (RTPS is backward compatible).
77 if (msg[4] != RTPS_VERSION[0] || msg[5] > RTPS_VERSION[1])
78 {
79 return false;
80 }
81
82 size_t off = Rtps::RTPS_HEADER_LEN;
83 while (off + 4 <= len)
84 {
85 uint8_t id = msg[off];
86 uint8_t flags = msg[off + 1];
87 uint16_t oth = (flags & Rtps::RTPS_FLAG_ENDIAN) ? (uint16_t)(msg[off + 2] | (msg[off + 3] << 8))
88 : (uint16_t)((msg[off + 2] << 8) | msg[off + 3]);
89 size_t body = oth ? oth : (len - (off + 4)); // 0 = extends to end of message
90 if (off + 4 + body > len)
91 {
92 return false;
93 }
94 if (cb)
95 {
96 cb(id, flags, body ? (msg + off + 4) : nullptr, body, arg);
97 }
98 off += 4 + body;
99 if (oth == 0)
100 {
101 break; // a 0-length terminates the message
102 }
103 }
104 return true;
105}
106
107#endif // PC_ENABLE_DDS
DDS / RTPS wire-protocol codec (PC_ENABLE_DDS).