Skip to content

Commit 9d221a9

Browse files
committed
feat(protocol): discover advertised OCF secure ports
1 parent d7b1c5e commit 9d221a9

5 files changed

Lines changed: 1556 additions & 0 deletions

File tree

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,35 @@ python -m smartthings_local.protocol.dtls_probe "$APPLIANCE_IP" 5684 49153 49154
278278

279279
`live` means a DTLS server answered its first flight; `dead` means silent or not DTLS. Once you have the client cert (Part 2), add the explicit `--diagnostic` flag to run the stateful diagnostic drive, which reports `completed` (cert accepted) or `rejected` with the server's fatal alert. Diagnostic mode can allocate appliance-side DTLS state and is never used by discovery or reconnect. An `unsupported_certificate` / `unknown_ca` alert means the endpoint is reachable but this certificate profile was rejected. It is not a reason to disable verification or keep retrying. The same bounded stateless API gates the bridge's reconnect loop and, when `OCF_PORT` is unset, probes both standard 5684 and ports 49152–49160.
280280

281+
Consumers can discover ports outside that fallback range through the public,
282+
read-only OCF resource directory before probing them:
283+
284+
```python
285+
from smartthings_local.protocol.dtls_probe import probe_dtls_ports
286+
from smartthings_local.protocol.ocf_discovery import discover_ocf_secure_ports
287+
288+
fallback_ports = (5684, *range(49152, 49161))
289+
advertisement = discover_ocf_secure_ports(appliance_host)
290+
candidates = advertisement.ports or fallback_ports
291+
probe = probe_dtls_ports(appliance_host, candidates)
292+
```
293+
294+
`discover_ocf_secure_ports()` first reads the public `/oic/res` directory and
295+
uses only `coaps://` endpoints whose literal host matches the correlated
296+
response source. If that first lookup yields no correlated response or no
297+
usable secure endpoint, the same overall deadline also bounds a filtered
298+
`/oic/res?rt=oic.r.doxm` fallback for Samsung's legacy secure-port policy. It
299+
accepts Samsung's dynamic plaintext response source port while still requiring
300+
the resolved target address and CoAP token, and assembles Block2 responses
301+
within fixed time, block-count, and payload limits.
302+
303+
Directory discovery and the DTLS probe have separate jobs: discovery can learn
304+
a device-advertised port outside the caller's fixed fallback set, while
305+
`probe_dtls_ports()` only checks the candidates it receives for a stateless
306+
DTLS first-flight response. Neither step authenticates the appliance. An
307+
advertised port therefore remains only a candidate: require a successful
308+
stateless DTLS probe before attempting authentication.
309+
281310
### Tested combinations
282311

283312
| Appliance class | Model family | Confirmed |
@@ -605,6 +634,7 @@ smartthings_local/ The installable library — `pip install sm
605634
dtls_session.py DTLS session: handshake, client-cert auth (file or in-memory PEM), Block2, liveness
606635
dtls_probe.py Stateless DTLS liveness + opt-in stateful diagnostic
607636
dtls_handshake.py Shared memory-BIO handshake driver, bounded by a monotonic deadline (used by session + probe)
637+
ocf_discovery.py Bounded public OCF secure-port discovery
608638
ocf_root_ca.pem Samsung OCF root CA, bundled for handshake verification
609639
ocf/ OCF resource + state layer (reusable)
610640
__init__.py

0 commit comments

Comments
 (0)