TCP window scaling: change tcp_pcb::acked to u32_t when window scaling is enabled to prevent an overflow when more than 64 Kbytes are ACKed

This commit is contained in:
Simon Goldschmidt 2014-02-07 11:32:02 +01:00
parent 2dab478c3f
commit a44e2190d6
2 changed files with 20 additions and 6 deletions

View File

@ -345,11 +345,24 @@ tcp_input(struct pbuf *p, struct netif *inp)
called when new send buffer space is available, we call it
now. */
if (pcb->acked > 0) {
TCP_EVENT_SENT(pcb, pcb->acked, err);
u16_t acked;
#if LWIP_WND_SCALE
/* pcb->acked is u32_t but the sent callback only takes a u16_t,
so we might have to call it multiple timess. */
u32_t pcb_acked = pcb->acked;
while(pcb_acked > 0) {
acked = (u16_t)LWIP_MIN(pcb_acked, 0xffffu);
pcb_acked -= acked;
#else
{
acked = pcb->acked;
#endif
TCP_EVENT_SENT(pcb, (u16_t)acked, err);
if (err == ERR_ABRT) {
goto aborted;
}
}
}
if (recv_data != NULL) {
LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
@ -991,8 +1004,9 @@ tcp_receive(struct tcp_pcb *pcb)
/* Reset the retransmission time-out. */
pcb->rto = (pcb->sa >> 3) + pcb->sv;
/* Update the send buffer space. Diff between the two can never exceed 64K? */
pcb->acked = (u16_t)(ackno - pcb->lastack);
/* Update the send buffer space. Diff between the two can never exceed 64K
unless window scaling is used. */
pcb->acked = (tcpwnd_size_t)(ackno - pcb->lastack);
pcb->snd_buf += pcb->acked;

View File

@ -244,7 +244,7 @@ struct tcp_pcb {
tcpwnd_size_t snd_wnd; /* sender window */
tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */
u16_t acked;
tcpwnd_size_t acked;
tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */
#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3)