Skip to content

feat: TunnelMqttTransport — MQTT over the existing WebSocket (single TLS session) - #25

Open
ACEFGI wants to merge 3 commits into
mainfrom
feat/tunnel-mqtt-transport
Open

ACEFGI wants to merge 3 commits into
mainfrom
feat/tunnel-mqtt-transport

Conversation

@ACEFGI

@ACEFGI ACEFGI commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • TunnelMqttTransport — MQTT 3.1.1 (QoS 0 only) over a caller-supplied byte pipe: setPipeSend(fn) / injectBytes() / notifyPipeUp(bool), exposing the MqttTransport API subset consumers use (setClientId, subscribe/unsubscribe, publish, topic-aware onMessage, send(doc, opts)). Keepalive via PINGREQ/PINGRESP with 1.5× timeout; subscriptions replay automatically after every reconnect; QoS/retain accepted for drop-in compatibility and always sent as QoS 0.
  • MqttCodec — the QoS-0 packet codec underneath: encoders with golden-byte tests against the 3.1.1 spec, and an incremental decoder that tolerates arbitrary stream splits, skips packet types outside the subset, and bounds packet/topic sizes.
  • WebSocketTransport tagged binary frames — sendBinaryTagged(tag, data, len) / onBinaryTagged(cb): a 1-byte application-defined channel tag inside the same WS frame, mechanism only. Registering onBinaryTagged claims the single binary receive slot (last registration wins, per Courier's callback model).
  • Version 0.7.0-dev, changelog and API reference updated.

Byte-pipe design keeps the transport fully host-testable: 48 new native test cases (23 codec, 25 transport) plus 5 tagged-frame tests on the WS transport.

Closes #24. Downstream halves: inanimate-tech/hawthorn-firmware#157 (adoption, opt-in flag), inanimate-tech/hawthorn-worker#157 (server demux). Motivation and hardware measurements: inanimate-tech/hawthorn-firmware#156.

Test plan

  • ./tools/run-tests.py static-analysis — 0 errors
  • ./tools/run-tests.py unit — 216/216 (48 new)
  • ./tools/run-tests.py build — example builds pass (includes gnu++11 dialect)
  • End-to-end against the worker tunnel (tracked in the downstream PRs)

@genmon for review.

🤖 Generated with Claude Code

ACEFGI and others added 3 commits August 21, 2026 14:47
…TLS session)

MQTT 3.1.1 QoS-0 codec + transport over a caller-supplied byte pipe, and
tagged binary frames on WebSocketTransport (1-byte channel tag, mechanism
only). Version 0.7.0-dev + changelog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… is refused

Hosts may poll notifyPipeUp every loop tick; without pacing, a failing
pipe write would retry CONNECT per tick.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…the transitive include)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TunnelMqttTransport: MQTT over the existing WebSocket (single TLS session)

1 participant