Radix 16 (live-verified), universal reply splitter, golden capture vectors, host_probe6

This commit is contained in:
kfj001 committed 2026-10-16 02:50:23 +00:00
1 parent 0cd6b34a2e
commit 62e0fd649b
10 files changed
+418 -82

No files matched your search

+19 -12
View File
@@ -29,6 +29,7 @@ from .protocol import (
SocketFrameDecoder,
decrypt_data,
decrypt_request,
decrypt_wire,
direct_connect_request,
encrypt_object,
frame_socket_payload,
@@ -64,8 +65,8 @@ class LocalDeviceClient:
:param socket_port: local TCP socket port (candidate 18000).
:param verify: TLS verification for the device API (device likely serves a
self-signed cert, so ``False`` is the practical default).
:param key_radix: key parse radix for the envelope cipher (32, per the
``int.tryParse(key, radix: 32)`` call in both directions).
:param key_radix: key parse radix for the envelope cipher (16 —
default ``int.tryParse`` radix, verified against live captures).
:param timeout: per-request timeout in seconds.
"""
@@ -77,7 +78,7 @@ class LocalDeviceClient:
scheme: str = "https",
verify: Optional[bool] = False,
socket_port: Optional[int] = None,
key_radix: int = 32,
key_radix: int = 16,
timeout: float = 10.0,
extra_headers: Optional[Dict[str, str]] = None,
session: Optional[requests.Session] = None,
@@ -185,7 +186,7 @@ class LocalDeviceClient:
"""
if envelope is None:
envelope = direct_connect_request(
cmd, equip_no or self.sn, data=data,
cmd, self.sn if equip_no is None else equip_no, data=data,
snno=self._sn_seq.next(),
)
return self.send_envelope(envelope)
@@ -194,8 +195,9 @@ class LocalDeviceClient:
wire = encrypt_object(envelope.to_json_string(), self.key,
radix=self.key_radix)
raw = self._socket_roundtrip(frame_socket_payload(wire))
reply = decrypt_data(raw, radix=self.key_radix)
if not reply:
try:
reply = decrypt_wire(raw, radix=self.key_radix)
except ValueError:
raise ConnectionError(
f"undecodable reply ({len(raw)} bytes) from "
f"{self.socket_host}:{self.socket_port}"
@@ -224,7 +226,10 @@ class LocalDeviceClient:
)
reply: Optional[Dict[str, Any]] = None
if reply_raw:
decoded = decrypt_data(reply_raw, radix=self.key_radix)
try:
decoded = decrypt_wire(reply_raw, radix=self.key_radix)
except ValueError:
decoded = ""
if decoded:
try:
reply = json.loads(decoded)
@@ -268,11 +273,13 @@ class LocalDeviceClient:
break
if collect_only:
return bytes(received)
if decrypt_data(bytes(received), radix=self.key_radix):
return bytes(received)
raise ConnectionError(
f"no reply frame from {self.socket_host}:{self.socket_port}"
)
try:
decrypt_wire(bytes(received), radix=self.key_radix)
except ValueError:
raise ConnectionError(
f"no reply frame from {self.socket_host}:{self.socket_port}"
)
return bytes(received)
# ------------------------------------------------------- convenience RPCs
def query_device_info(self) -> Dict[str, Any]: