reset recv parser if it takes too long for the message to arrive. (#17845)

i have a tuyamcu based device that occasionally gets a flipped bit in
messages it receives from the muc. those usually show up as checksum
failures, but if the bit flips in the length field then we wait for
bytes that just arent going to arrive, so we don't get to the cksum
field for that test to fail. instead, add a timeout that the tick
checks, and reset the recv state machine on a timeout.

if the message that was corrupted was a dp update, we'll end up with
an inconsistent view of the state of the DPs. maybe we should send a
request for all datapoint values when this or a cksum failure happens?
This commit is contained in:
David Gwynne 2023-02-01 20:48:07 +10:00 committed by GitHub
parent 293ae8064d
commit 052b5c2926
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 11 additions and 0 deletions

View File

@ -380,6 +380,7 @@ tuyamcubr_parse(struct tuyamcubr_softc *sc, uint8_t byte)
if (byte != TUYAMCUBR_H_TWO)
return (TUYAMCUBR_P_START);
p->p_deadline = sc->sc_clock + (10 * 1000);
nstate = TUYAMCUBR_P_VERSION;
break;
case TUYAMCUBR_P_VERSION:
@ -889,6 +890,16 @@ tuyamcubr_tick(struct tuyamcubr_softc *sc, unsigned int ms)
sc->sc_clock += ms;
if (sc->sc_parser.p_state >= TUYAMCUBR_P_VERSION) {
/* parser timeout only starts after the header */
diff = sc->sc_clock - sc->sc_parser.p_deadline;
if (diff > 0) {
AddLog(LOG_LEVEL_ERROR,
TUYAMCUBR_FMT("recv timeout"));
sc->sc_parser.p_state = TUYAMCUBR_P_START;
}
}
diff = sc->sc_clock - sc->sc_deadline;
if (diff < 0) {
/* deadline hasn't been reached, nothing to do */