Repository navigation
Fix response byte accounting after partial TCP writes - #509
Conversation
mathieucarbou
left a comment
There was a problem hiding this comment.
@labodj : we won't accept an AI-generated PR fixing a maybe issue (because it does not take into account how lwip / async_tcp works behind).
Please get rid of all this AI crap, and work on a real reproductible test case like we have in our examples that can prove the issue is real and reproductible with an ESP32.
|
@willmmiles : I will let you verify - this relates to how lwip works so you'll be better at answering this PR ;-) Thanks! |
|
Thanks for the review. |
|
@labodj fyi @willmmiles did some verifications and the issue is valid also on esp32 - we will fix it through another pr. Thanks for letting us know about it! |
Right this one is harder to test and depends on lwip behaviour. But the fix is still valid: each time we call add or write we should increase the payloadlen and it impacts But on ESP32, And payloadlen only impacts the |
When
AsyncClient::add()accepts only part of a pending response buffer,AsyncAbstractResponse::write_send_buffs()advances the buffer offset and breaks before adding the accepted bytes topayloadlen. For example, accepting 7 of 20 bytes queues those 7 bytes but returns 0 and leaves_writtenLengthand the in-flight accounting behind.Move
payloadlen += added_lenimmediately afteradd(), so every accepted byte is counted before the partial-write branch. Buffer retention and subsequent retries continue to use the existing code.The regression test compiles the actual production method with a controllable TCP peer. It checks zero acceptance and acceptance limits of 1, 7, 19 and 20 bytes, with chunk in-flight tracking both enabled and disabled. It verifies the returned byte count, cumulative written bytes, in-flight bytes, retained buffer offset and exact final payload. Eight of the ten scenarios fail against unchanged
main; all ten pass with this fix.Native tests pass with both GCC and Clang under AddressSanitizer and UBSan. Run them with:
The included workflow runs the same tests with both compilers. The TCP double exercises the short-write contract; it does not emulate lwIP or the radio.
Build verification
Local builds passed for:
d1_miniPerfTestsesp32devPerfTestsesp32devPerfTestsesp32-c3-devkitm-1PerfTestsrpipicowPerfTestsrpipico2wPerfTestsgeneric-bk7231n-qfn32-tuyaAsyncResponseStreamgeneric-rtl8710bn-2mb-788kAsyncResponseStreamESP32 Arduino 3.3.11 was built from the official git tag with the matching IDF
b774170flibraries. LibreTiny was built in an isolated Python 3.12 / PlatformIO 6.1.19 environment. These are compilation checks; no boards were flashed.