The read timeout was kept in 16 bits, so a longer one wrapped: Berry's
webclient.set_timeouts(80000) gave up after about 14.5 s, and 70000
after 4.5 s. Keep it in 32 bits, in HttpClientLight and
AsyncHttpClientLight, as ESPEasy's copy of the client now does.
Matter_TLV.tlv2raw() wrote a UTF2 string with bytes().frostring(), a
typo for fromstring(), so encoding any string of more than 255 bytes
(which is given type UTF2 automatically) raised attribute_error.
WifiManagerBegin() turned the AP on with WifiSetMode() and named it with
WiFi.softAP() only after WifiSetMode()'s delay(100): for that time the AP
beaconed under the SDK's default name, ESP_ and the AP MAC, which a phone
or computer then lists beside the real name, often for a minute after.
WiFi.softAP() turns the AP on and names it at once, so it now comes first;
WifiSetMode() then sets the station side as before.
wc_errorCodeMessage() passed httpCode as well as the elapsed time to the
"Connection timeout after %d ms" format, so the log showed the code:
"HTP: Connection timeout after -1 ms".
* AsyncHttpClientLight: time out reading a body when the server goes silent
writeToStreamDataBlock() waited for the rest of a body for as long as
connected() held. A server that stops sending part way through without
closing leaves connected() true, so the worker never finishes and the
caller, waiting in runJob(), never returns. Give up after _tcpTimeout
without data and return HTTPC_ERROR_READ_TIMEOUT, as HttpClientLight
now does (#25139).
* AsyncHttpClientLight: notice when the server closes after the last byte
AsyncTcpAdapter only saw the peer close inside read(), and callers only
read when available() > 0. A body without Content-Length that ends with
the server closing left connected() true for ever, so
writeToStreamDataBlock() never returned. connected() now peeks at the
socket, as WiFiClient::connected() does: data still buffered keeps it
connected, an orderly close after it does not.
* AsyncHttpClientLight: address review of the read timeout
- connected() only reports a peer close and no longer calls stop(): it can
be called from another task than the worker using the socket.
- writeToStreamDataBlock() closes the connection on a read timeout, as the
chunked readers do, so a stalled connection is not reused.
- readBodyToStreamString(): the identity branch used by async GET/POST now
times out after _tcpTimeout without data, and notices a close: with no
Content-Length it ends the body, with one it is a lost connection.
After the zero-size chunk the readers read one line unconditionally,
then waited for another empty line. The first read already consumed the
empty line that ends the body, so every chunked body waited for a line
that never came and failed with HTTPC_ERROR_READ_TIMEOUT after
_tcpTimeout. Read trailer lines up to the first empty one instead.
writeToStreamDataBlock() looped for as long as connected() held, waiting
for the rest of the body with no time limit. A server that stops sending
part way through a body without closing the connection - a computer that
sleeps, a cable pulled, a network that drops between the two ends - leaves
connected() true for ever, so the read never returned. Called from the main
loop, as Berry's webclient get_string() is, it left the device answering
nothing, not even its web page, until it was power-cycled.
Give up after _tcpTimeout without data, returning HTTPC_ERROR_READ_TIMEOUT,
as handleHeaderResponse() already does for the headers. A body that keeps
arriving, however slowly, is unaffected: each piece resets the clock.