fix: s3parser now looks for bare ETX, not DLE+ETX.
This commit is contained in:
@@ -155,8 +155,16 @@ class S3FrameParser:
|
|||||||
State machine:
|
State machine:
|
||||||
IDLE — scanning for DLE (0x10)
|
IDLE — scanning for DLE (0x10)
|
||||||
SEEN_DLE — saw DLE, waiting for STX (0x02) to start a frame
|
SEEN_DLE — saw DLE, waiting for STX (0x02) to start a frame
|
||||||
IN_FRAME — collecting de-stuffed payload bytes
|
IN_FRAME — collecting de-stuffed payload bytes; bare ETX ends frame
|
||||||
IN_FRAME_DLE — inside frame, saw DLE; ETX ends frame, DLE continues stuffing
|
IN_FRAME_DLE — inside frame, saw DLE; DLE continues stuffing;
|
||||||
|
DLE+ETX is treated as literal data (NOT a frame end),
|
||||||
|
which lets inner-frame terminators pass through intact
|
||||||
|
|
||||||
|
Wire format confirmed from captures:
|
||||||
|
[DLE=0x10] [STX=0x02] [stuffed payload+chk] [bare ETX=0x03]
|
||||||
|
The ETX is NOT preceded by a DLE on the wire. DLE+ETX sequences that
|
||||||
|
appear inside the payload are inner-frame terminators and must be
|
||||||
|
treated as literal data.
|
||||||
|
|
||||||
ACK (0x41) bytes and arbitrary non-DLE bytes in IDLE state are silently
|
ACK (0x41) bytes and arbitrary non-DLE bytes in IDLE state are silently
|
||||||
discarded (covers device boot string "Operating System" and keepalive ACKs).
|
discarded (covers device boot string "Operating System" and keepalive ACKs).
|
||||||
@@ -210,6 +218,11 @@ class S3FrameParser:
|
|||||||
elif self._state == self._IN_FRAME:
|
elif self._state == self._IN_FRAME:
|
||||||
if b == DLE:
|
if b == DLE:
|
||||||
self._state = self._IN_FRAME_DLE
|
self._state = self._IN_FRAME_DLE
|
||||||
|
elif b == ETX:
|
||||||
|
# Bare ETX = real frame terminator (confirmed from captures)
|
||||||
|
frame = self._finalise()
|
||||||
|
self._state = self._IDLE
|
||||||
|
return frame
|
||||||
else:
|
else:
|
||||||
self._body.append(b)
|
self._body.append(b)
|
||||||
|
|
||||||
@@ -219,10 +232,11 @@ class S3FrameParser:
|
|||||||
self._body.append(DLE)
|
self._body.append(DLE)
|
||||||
self._state = self._IN_FRAME
|
self._state = self._IN_FRAME
|
||||||
elif b == ETX:
|
elif b == ETX:
|
||||||
# End of frame
|
# DLE+ETX inside a frame is an inner-frame terminator, NOT
|
||||||
frame = self._finalise()
|
# the outer frame end. Treat as literal data and continue.
|
||||||
self._state = self._IDLE
|
self._body.append(DLE)
|
||||||
return frame
|
self._body.append(ETX)
|
||||||
|
self._state = self._IN_FRAME
|
||||||
else:
|
else:
|
||||||
# Unexpected DLE + byte — treat both as literal data and continue
|
# Unexpected DLE + byte — treat both as literal data and continue
|
||||||
self._body.append(DLE)
|
self._body.append(DLE)
|
||||||
|
|||||||
Reference in New Issue
Block a user