mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
A file larger than the output buffer is sent in two phases: the first buffer goes out in MSS-sized pieces, with o_idx walking through it, and what is left is then streamed from flash a chunk at a time into outbuf from offset 0. The continuation branch never reset o_idx, so it kept the offset the first phase had left it at, while uip_rexmit() retransmits from outbuf + o_idx. A lost continuation segment was therefore retransmitted as the bytes 1460 further into the buffer, which the client accepts as the missing data, and with o_idx + slen past the 2500-byte buffer it also read whatever xdata follows outbuf. Reproduced on a SWTGW218AS by dropping 15% of the switch's TCP segments: seven of eight fetches of a 21 kB static came back the right length and the wrong content, each first differing at a fixed phase of the 1460-byte chunk. With o_idx reset the retransmission repeats the chunk it sent. The o_idx += slen right after slen = 0 went too: it added nothing. (cherry picked from commit 789d29423288f89411a41673e26ce1854b296c3d)