Skip to content

feat(protocol): discover known-host OCF responder ports - #47

Merged
QuiteYellow merged 1 commit into
QuiteYellow:mainfrom
Moballo-LLC:codex/ocf-multicast-responder
Aug 21, 2026
Merged

feat(protocol): discover known-host OCF responder ports#47
QuiteYellow merged 1 commit into
QuiteYellow:mainfrom
Moballo-LLC:codex/ocf-multicast-responder

Conversation

@Jason-Morcos

@Jason-Morcos Jason-Morcos commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add bounded IPv4 multicast discovery for the plaintext OCF response port of one known host
  • send unfiltered current OCF and legacy IoTivity directory requests, plus the tested legacy DOXM-filtered fallback, on an explicitly selected LAN interface
  • accept only token-correlated CoAP 2.05 responses from the expected address
  • return redacted, bounded candidate results with fixed failure codes

Why

The moving plaintext responder port is one of the remaining package-level gaps described in mbillow/localthings#388. Some devices receive discovery on UDP 5683 but reply from a different source port, and that source port can change after a power cycle.

This fills the multicast-capable path without making identity claims about an unauthenticated UDP response. It composes with #36: this helper finds the plaintext responder port for a known host, #36 can query /oic/res there for the advertised secure endpoint, and the existing DTLS probe plus authenticated session validate the final candidate.

The first two request profiles match the working appliance integration. The filtered legacy fallback covers the older TV and soundbar behavior reported on #36 without narrowing the requests used by the installed washer/dryer generations.

The helper uses one monotonic deadline across at most four rounds, caps received datagrams and distinct ports, closes its socket on every return path, and fails closed if too many ports answer.

Validation

  • 274 SmartThings-Local tests
  • 1,625 LocalThings tests with this checkout first on PYTHONPATH
  • exact modern and legacy request-vector coverage, including a responder that answers only one profile
  • distribution contents verified for wheel and sdist
  • share-safety scan and bytecode compilation

@vmonkey

vmonkey commented Aug 19, 2026

Copy link
Copy Markdown

Tested this branch against two Samsung OCF devices with dynamic response ports: a soundbar (oic.d.networkaudio, HW-S61B) and a Tizen TV (oic.d.tv, UE50TU7172). Wired, multi-homed host, interface_address passed explicitly.

20/20 hits on each, ports matching an independent sweep run at the same time.

One note: every call takes the full timeout — 3.00s on all 40 runs with the defaults. Each round listens out its slice even after the target has answered, and there's no early exit. With --timeout 0.5 --rounds 1 I still get 5/5, so responses arrive well inside the window. Since target_address is required and results are filtered to that source, could it return once the expected host answers? If draining is deliberate for collecting multiple candidates, ignore this.

@QuiteYellow

Copy link
Copy Markdown
Owner

Merging this one.

TTL 1 so it cannot leave the subnet, multicast loopback off, caps on datagram size, datagrams per round and distinct ports, one monotonic deadline across all rounds, and every socket closed on every return path.

@vmonkey's two-device result is what moved it from plausible to tested.

Separately: #36, #48, #49, #50 and #54 all collide with each other in dtls_session.py, and two of them are building the same MID registry from opposite ends.

@QuiteYellow
QuiteYellow merged commit 4999e8b into QuiteYellow:main Aug 21, 2026
8 checks passed
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.

3 participants