Skip to content

Releases: SoundMatt/cpp-DDS

v0.25.1 — audit fix pass (spec version, IDL silent stubs, CLI capabilities, CI gates)

Choose a tag to compare

@SoundMatt SoundMatt released this 30 Jul 21:29
c472ecb

Fixes 8 of 9 findings from the 2026-07-30 x-Net audit pass, each independently re-verified before applying:

  • kRelaySpecVersion/kSpecVersion: 1.11 → 2.0; dds::kSpecVersion is now a true alias of relay::kRelaySpecVersion instead of an independently hardcoded literal that could drift.
  • IDL generator (src/idl/gen.cpp) now hard-errors instead of silently emitting // TODO: encode/decode stub comments for nil sequence/array element types, unresolved struct references, and cyclic structs.
  • CLI capabilities now advertises "rtps" transport and "loaning"/"tsn" features (RELAY spec §12.2), reflecting shipped functionality that was previously under-reported.
  • from_message no longer silently discards a malformed dds.writer_guid; it clears the GUID and returns ErrSampleRejected.
  • ROADMAP.md/CLAUDE.md: corrected stale spec-version claims, hardcoded per-developer paths, stale close_with_drain() checkbox.
  • CI: removed || true masking from cpfusa init steps; aligned pinned --project-version with the actual project version.

Two CI-gate sub-changes proposed in the same finding were evaluated and not applied because they would have broken CI on every run: raising --sec-tested from 96 to 100 (real coverage measured at 96.7%) and switching cpfusa cyber --write to a --check flag that does not exist on the pinned cpp-FuSa v0.17.1 CLI. See CHANGELOG.md for full detail.

Build verified clean; full suite passes (ctest 666/666).

See CHANGELOG.md for full detail.

v0.25.0

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 12:39
465115d

dds::bridge::rest — HTTP/SSE gateway bridging a dds::IParticipant to HTTP clients (#39). Fixed a Windows/MSVC CTest test-name encoding issue (em-dash in a Catch2 TEST_CASE name) that blocked the original merge.

v0.24.0 — WAN bridge (dds::bridge::wan)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 09:47
1b65ee6

Added

  • dds::bridge::wan (include/dds/bridge/wan/wan.hpp, src/bridge/wan/wan.cpp) — a WAN bridge forwarding DDS samples between two dds::IParticipant domains over a real TCP connection, the second item of ROADMAP.md's "Tier 4 — bridges" and a C++ port of go-DDS's bridge/wan package. Landed as a second member of cppdds_bridges. Bridge::serve accepts TCP connections and publishes received samples to a local participant (a fresh per-connection publisher cache, matching go's per-call receiveLoop exactly); Bridge::connect synchronously subscribes to Options::topics before dialing (with cleanup-on-partial-failure) and streams each topic's samples to the server from an independent per-topic sender thread. Wire format is byte-exact with go's encoding/json.Marshal output for the unexported wireFrame struct (a 4-byte big-endian length prefix, capped at 16 MiB, followed by {"t":"<topic>","p":"<base64-payload>"}), verified against reference vectors captured from a real go-DDS process. Per this baseline's explicit scope (see wan.hpp's file-level scope note), the shared-token auth path is included alongside the framing it depends on (Options::token, write_auth/read_auth, constant-time server-side comparison, silent connection drop on mismatch); a real TLS/mTLS transport remains the explicitly-deferred stretch item. Also adds dds::mock::create's isolated_broker parameter (REQ-MOCK-006, additive, default false) — a C++ port of go-DDS's mock.IsolatedBroker(), needed to test two same-process participants standing in for two separate DDS domains without one echoing directly to the other.
  • Verified with 34 new tests (tests/test_bridge_wan.cpp) plus 2 new dds::mock tests — 617/617 tests total. REQ-BRIDGE-WAN-001 through REQ-BRIDGE-WAN-007 and REQ-MOCK-006 added, traced and tested. ROADMAP.md's wan bullet checked off (rest remains open).

Fixed

  • Bridge::close()'s socket force-close now calls shutdown() before close() — required on Linux to reliably unblock a peer thread concurrently blocked in recv() on the same fd (a real cross-platform correctness fix, not just a test artifact: close() alone doesn't reliably wake a blocked reader on another thread per POSIX, only observed to work that way on macOS/BSD).

v0.23.0 — gRPC protocol bridge (dds::bridge::grpc)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 08:47
8fe8744

Added

  • dds::bridge::grpc (include/dds/bridge/grpc/{grpc.hpp,transport.hpp,config.hpp}, src/bridge/grpc/{grpc.cpp,transport.cpp,config.cpp}) — a gRPC gateway bridging a dds::IParticipant to RPC clients over JSON-encoded messages, the first item of ROADMAP.md's "Tier 4 — bridges" and a C++ port of go-DDS's bridge/grpc package. Landed as the first member of a new cppdds_bridges CMake target (CPPDDS_BUILD_BRIDGES, default ON) — the first concrete piece of the previously-proposed ddsbridges target group; cppdds_lib itself is untouched. SubscribeRequest/PublishRequest/Sample/PublishAck and their JSON codec are byte-exact with go-DDS's encoding/json.Marshal output, verified against reference vectors captured from a real go-DDS process. Bridge implements the three RPCs (subscribe/publish/stream_publish) as plain C++ methods against SampleSender/PublishReceiver abstractions, independent of any networking, plus lazy subscriber/publisher caching, Options (auth_token/qos/filter/transform), and check_auth(). transport.hpp's Server/Client speak a real, working TCP wire protocol (a text header block plus real gRPC length-prefixed-message framing) rather than a full HTTP/2 gRPC transport — this repo has no HTTP/2 or protobuf dependency anywhere — documented in full in grpc.hpp's file-level scope note. config.hpp/config.cpp hand-roll a minimal YAML-subset parser for the bridge's listen/auth_token/topics schema.
  • Verified with 41 new tests (tests/test_bridge_grpc.cpp) — 581/581 tests total. REQ-BRIDGE-GRPC-001 through REQ-BRIDGE-GRPC-011 added, traced and tested. ROADMAP.md's grpc bullet checked off (wan/rest remain open).

v0.22.0 — TSN (IEEE 802.1) QoS integration (dds::tsn)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 07:32
642334b

Added

  • dds::tsn::Stream/StreamConfig (include/dds/tsn/tsn.hpp, src/tsn/tsn.cpp) — a C++ port of go-DDS's tsn/tsn.go, the fourth and last item of ROADMAP.md's "Tier 3 — xtypes, tsn, idl, cdr" (now fully complete). load_config()/parse_config() parse the identical JSON tsn_streams shape via a small internal recursive-descent JSON reader scoped to exactly this config shape, matching this repo's established small-purpose-built-parser convention rather than a general-purpose dependency.
  • include/dds/rtps/tsn.hpp mirrors go-DDS's rtps/tsn.go split exactly: TSNParams/TSNStreamConfig live inside dds::rtps itself so dds::rtps never depends on dds::tsn. dds::tsn::StreamConfigAdapter/with_stream_config() is the adapter, assigned to a new ParticipantOptions::tsn_config field.
  • include/dds/tsn/taprio.hpp + src/tsn/taprio.cpp — TAPRIOEntry/TAPRIOConfig (gate control list, cycle_duration()/validate()/tc_command()) plus taprio_from_streams(), all portable. src/tsn/taprio_linux.cpp (compiled only when CMAKE_SYSTEM_NAME is "Linux", mirroring Tier-1 phase 3's traffic_linux.cpp/traffic_other.cpp split) programs and verifies the real Linux taprio qdisc via hand-built RTM_NEWQDISC/RTM_GETQDISC netlink messages over NETLINK_ROUTE — a byte-for-byte port of go-DDS's tsn/taprio_linux.go attribute layout, cross-checked field-by-field against a fresh go-DDS clone. src/tsn/taprio_other.cpp returns a documented "requires Linux" diagnostic everywhere else. Neither apply() nor any TSN code is called automatically by dds::rtps::Participant, matching go-DDS's own participant.go.
  • Real Participant/Writer wiring, not just types: ParticipantOptions::tsn_config set → new_publisher resolves each writer's topic against it (config match takes priority, QoS::transport_priority — a field that already existed — is the fallback PCP selector) and lazily creates/reuses one dedicated UdpSocket per distinct PCP value, configured via the already-existing (Tier-1 phase 3) dds::rtps::traffic.hpp hooks that had no caller anywhere in the codebase before this item. Writer::write()/send_heartbeat() route through that dedicated socket, computing a SO_TXTIME launch time for streams with a nonzero tx_offset. A TSN stream's max_frag_payload() overrides fragment.hpp's default fragmentation threshold end-to-end.
  • 4 new cross-participant, real-loopback-UDP end-to-end tests plus 45 unit tests mirroring go-DDS's tsn_test.go/taprio_test.go matrices — 540/540 tests total. REQ-TSN-001 through REQ-TSN-007 added, traced and tested.

Verified locally: Release C++17/C++20 builds clean, ctest 540/540, Debug ASan+UBSan pass on both macOS and a real Ubuntu-22.04/gcc-12 Docker container (exercising the actual Linux netlink code path). CI: all 13 checks green (Linux/macOS/Windows matrix, gcc-12 ASan+UBSan, cpp-FuSa full lifecycle).

Full changelog: https://github.com/SoundMatt/cpp-DDS/blob/main/CHANGELOG.md#0220--2026-07-28

v0.21.0 — OMG IDL parser + C++ code generator (dds::idl / ddstool)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 06:22
8113dc7

Added

  • dds::idl (include/dds/idl/idl.hpp, src/idl/parser.cpp, src/idl/gen.cpp) — an OMG IDL lexer/parser plus a C++ code generator, a faithful C++ port of go-DDS's tools/idl package, the third item of ROADMAP.md's "Tier 3 — xtypes, tsn, idl, cdr". Parses module (nestable)/struct/enum/typedef declarations, basic types, bounded/unbounded sequences, bounded strings, fixed-size arrays, qualified Module::Name references, and the @key annotation. Generates a self-contained C++ header: a struct/enum class/using-alias per declaration plus a <Name>Codec built on dds::cdr::Encoder/Decoder (Tier 3, cdr, v0.20.0), with nested-struct inlining and a cycle guard. Two go-DDS quirks independently confirmed against a fresh go-DDS clone and faithfully preserved: the emitted namespace is always idlgen unless the root Module's name is overridden, and a parenthesized annotation argument (@id(5)) is a parse error.
  • ddstool (ddstool/cli.hpp, ddstool/cli.cpp, ddstool/main.cpp) — a new standalone CLI executable exposing ddstool idl [-out <file>] [-namespace <name>] <input.idl>, distinct from the existing cpp-dds RELAY-conformance CLI. Logic lives in a small ddstool_cli static library so it's testable in-process.
  • A checked-in round-trip fixture (tests/idl_roundtrip/schema.idl + schema_gen.hpp, produced by actually running the ddstool binary) mirroring go-DDS's own tools/idl/roundtrip/ package field-for-field. Header/Telemetry marshal() output verified byte-exact against reference vectors independently derived from a fresh go-DDS clone.
  • 101 new tests (tests/test_idl.cpp, tests/test_ddstool_cli.cpp, tests/idl_roundtrip/test_idl_roundtrip.cpp) — 500/500 tests total. Adds REQ-IDL-001 through REQ-IDL-009, traced and tested.

Verified locally: Release C++17 build clean, new files additionally compiled warning-clean under a genuine -std=c++20 invocation, ctest 500/500, Debug ASan+UBSan pass. CI: all 13 checks green (Linux/macOS/Windows matrix, gcc-12 ASan+UBSan, cpp-FuSa full lifecycle).

Full changelog: https://github.com/SoundMatt/cpp-DDS/blob/main/CHANGELOG.md#0210--2026-07-27

v0.20.0 — general-purpose CDR/XCDR1 codec (dds::cdr)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 05:38
2007841

Added

  • dds::cdr (include/dds/cdr/cdr.hpp, src/cdr/cdr.cpp) — general-purpose CDR/XCDR1 encode/decode per OMG DDS-XTypes 1.3, a faithful C++ port of go-DDS's top-level tools/cdr package, the second item of ROADMAP.md's "Tier 3 — xtypes, tsn, idl, cdr". Encoder/Decoder handle all CDR primitives with natural alignment, plus strings and byte sequences per the XCDR1 spec. Encoder prepends and Decoder::create() validates the 4-byte CDR_LE encapsulation header (accepting both CDR_LE and CDR_BE scheme values on decode, matching go-DDS's own quirk exactly).
  • Deliberately a SEPARATE library from Tier 1 phase 2's discovery-scoped dds::rtps::PLCDREncoder/PLCDRDecoder — not reused, not extended; mirrors go-DDS's own rtps/cdr.go vs. top-level tools/cdr/ package split.
  • Every method verified byte-exact against reference vectors independently derived from a fresh go-DDS clone.
  • 45 new tests (tests/test_cdr.cpp) — 443/443 tests total. Adds REQ-CDR-001 through REQ-CDR-005, traced and tested.

Verified locally: Release C++17 build clean, the new files additionally compiled warning-clean under a genuine -std=c++20 invocation directly, ctest 443/443, Debug ASan+UBSan pass on macOS/AppleClang. CI: all 13 checks green (Linux/macOS/Windows matrix, gcc-12 ASan+UBSan, cpfusa full lifecycle).

Full changelog: https://github.com/SoundMatt/cpp-DDS/blob/main/CHANGELOG.md#0200--2026-07-27

v0.19.0 — dds::xtypes (DDS-XTypes Dynamic Data support)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 05:11
aeaf6a3

dds::xtypes — DDS-XTypes Dynamic Data support

Implements the next Tier-3 roadmap item: a faithful C++ port of go-DDS's tools/xtypes/xtypes.go (Dynamic Data / runtime type system, loosely aligned with OMG DDS-XTypes 1.3), the first item of ROADMAP.md's "Tier 3 — xtypes, tsn, idl, cdr".

Added

  • dds::xtypes::TypeKind / FieldDescriptor / TypeDescriptor — the runtime schema model
  • dds::xtypes::identify() / TypeIdentifier — content-addressed type fingerprint (SHA-256 over a canonical JSON encoding, order-independent over field declaration)
  • dds::xtypes::DynamicData — schema-validated property map with to_json()/from_json(), unknown fields silently skipped on read (forward compatibility)
  • dds::xtypes::TypeRegistry — thread-safe, name-keyed store with structural-conflict detection (ErrTypeMismatch)
  • dds::xtypes::check_compatibility() — forward/backward schema-evolution rules

TypeIdentifier's canonical-JSON hash is verified byte-for-byte against reference vectors independently derived from a fresh go-DDS clone, including Go's default HTML-safe JSON string-escaping rule, confirmed against real go-DDS output rather than assumed. No external crypto dependency is fetched for this project, so SHA-256 is implemented from scratch under src/xtypes/detail/ (independent of dds::security's own scratch SHA-256, which is explicitly scoped to security.cpp only) and verified against FIPS 180-4 known-answer vectors.

Scope: internal, additive — dds::xtypes is a standalone type system and dynamic-data package, not wired into RTPS discovery or dds::adapt(), matching dds::safety::E2EPublisher's and dds::security::Plugin's own precedent.

Adds REQ-XTYPE-001 through REQ-XTYPE-006 and REQ-TREG-001 through REQ-TREG-003, traced and tested. Checks off the xtypes item in ROADMAP.md.

36 new tests (417/417 total), verified with Release C++17/C++20 builds and a Debug ASan+UBSan pass; CI additionally exercises Linux/gcc-12 ASan+UBSan.

v0.18.0 — dds::security (HMAC, AES-256-GCM, topic ACL, anti-replay)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 04:32
f41207a

dds::security — HMAC-SHA-256, AES-256-GCM, topic ACL, anti-replay

Implements the next Tier-2 roadmap item: a C++ port of go-DDS's security package (security/security.go, access.go, replay.go), immediately following the already-completed ddssafety/E2E item (v0.17.0).

Added

  • dds::security::HMACPlugin — HMAC-SHA-256 message authentication (plaintext || HMAC[32])
  • dds::security::AESGCMPlugin — AES-256-GCM authenticated encryption (nonce[12] || ciphertext || tag[16])
  • dds::security::AccessPolicy / Permission / Rule — per-topic ACL, first-match-wins glob rules (byte-oriented port of Go's path.Match)
  • dds::security::ReplayGuard — sliding-window anti-replay sequence-number enforcement

HMACPlugin/AESGCMPlugin wire formats are byte-for-byte identical to go-DDS's, verified against reference vectors independently derived from a fresh go-DDS clone. No external crypto dependency is fetched for this project, so SHA-256/HMAC/AES-256/GCM are implemented from scratch under src/security/crypto/ (internal, non-public) and independently verified byte-exact against FIPS 180-4 / RFC 4231 / NIST SP 800-38A known-answer test vectors, the classic McGrew-Viega/NIST AES-256-GCM all-zero test vector, and Go's actual crypto/aes + crypto/cipher + crypto/hmac stdlib output.

Scope: internal, additive — dds::security::Plugin is a standalone seal/open library, not wired into dds::adapt(), dds::mock, or the RTPS transport, matching dds::safety::E2EPublisher's own precedent. go-DDS's security.cert/security.discovery are out of scope, matching the E2E item's precedent.

Adds REQ-SECURITY-001 through REQ-SECURITY-009, traced and tested. Checks off the security item in ROADMAP.md.

Verification

  • Release C++17/C++20 builds clean across Linux/macOS/Windows, zero warnings
  • 381/381 tests pass (44 new)
  • Gcc-12 ASan+UBSan clean (reproduced locally in a matching Ubuntu-22.04 Docker container before pushing, after fixing a genuine UBSan finding — see 7a7cf27)
  • relay conform/relay interop --protocol DDS pass unchanged
  • cpfusa check/cyber/vuln/qualify all green

Full Changelog: v0.17.0...v0.18.0

v0.17.0 — ddssafety E2E protection wire header (Tier 2)

Choose a tag to compare

@SoundMatt SoundMatt released this 28 Jul 03:42
fe34d1e

[0.17.0] — 2026-07-27

Added

  • dds::safety::E2EPublisher / dds::safety::E2ESubscriber
    (include/dds/safety/e2e.hpp, src/safety/e2e.cpp) — a byte-compatible
    C++ port of go-DDS's end-to-end (E2E) data protection wire header
    (safety/e2e.go), the first item of ROADMAP.md's "Tier 2 — safety and
    security". E2EPublisher wraps a dds::IPublisher and prepends an
    18-byte little-endian protection header (DataID, SourceID,
    SequenceCounter, Timestamp, CRC-16/CCITT-FALSE) to every payload before
    writing, with a per-publisher sequence counter starting at 1.
    E2ESubscriber wraps a dds::ISubscriber, strips the header from every
    received sample on a background pump thread, and validates CRC,
    sequence-counter continuity, and sample freshness against
    E2EConfig::max_age (zero disables freshness checking) — valid samples
    are forwarded via channel(); violations are reported via errors()
    without suppressing delivery of sequence-gapped samples (matching
    go-DDS's own behavior).
  • Byte-exact wire-format vectors (18-byte header layout and the
    CRC-16/CCITT-FALSE algorithm) independently derived from a fresh go-DDS
    clone and checked in tests/test_safety_e2e.cpp, following the same
    reference-vector derivation convention test_rtps_cdr.cpp established
    for RTPS.
  • requirements/requirements.json gains REQ-E2E-001 through
    REQ-E2E-006, traced (fusa:req) and tested (fusa:test).

Internal/additive: E2EPublisher fully implements dds::IPublisher
(including the context-bounded write() overload, per REQ-SAFETY-003) —
a strict improvement over go-DDS's own E2EPublisher, which in practice
does not satisfy the full dds.Publisher interface (no WriteCtx).
E2ESubscriber is not forced into dds::ISubscriber for the same reason
go-DDS's own type isn't a full Subscriber either (no TryRead/
Unsubscribe); it exposes channel()/errors()/close() instead,
mirroring go-DDS's actual surface. go-DDS's safety.SafetyMetricsProvider/
SafetyEvent/monitor-integration layer (safety/metrics.go) is
Tier-5-adjacent observability and out of scope for this item.

Verified locally: Release C++17/C++20 clean, all tests passing, Debug
ASan+UBSan clean. ROADMAP.md checked off.