The frame-skip loops in checkRecvFrame subtract the return value of
client.read() from frame_length. On ESP32, WiFiClient::read() returns
-1 on error. Subtracting -1 increments frame_length instead of
decrementing it, turning the loop into an infinite hang.
A WiFi client can trigger this by sending a frame header with a large
length and then disconnecting (or sending fewer bytes than claimed).
The node locks up in the skip loop and stops processing all traffic.
Switch to single-byte client.read() which returns the byte value or -1,
and break out of the loop on error. Decrement frame_length by exactly 1
per successful read.