From cfbd603eeb19635d391dfafb74deb06611c9486a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 17 Oct 2013 09:54:48 -0600 Subject: net_sendfile: Let the ACK callback handle the REXMIT flag and don't return until all data has been ACK'd. From Max Holtzberg --- nuttx/ChangeLog | 6 ++++-- nuttx/net/net_sendfile.c | 45 +++++++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 7760eecbf..ac87c9a83 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -5787,5 +5787,7 @@ Max Holtzberg (2013-10-17). * net/uip/uip_tcpinput.c: Move tcp connection into SYN_RCVD state after aception instead of bypassing and moving directly into ESTABLISHED. - From Max Holtzber (2013-10-17). - + From Max Holtzberg (2013-10-17). + * net/net_sendfile.c: Let the ACK callback handle the REXMIT flag and + don't return until all data has been ACK'd. From Max Holtzberg + (2013-10-17). diff --git a/nuttx/net/net_sendfile.c b/nuttx/net/net_sendfile.c index 2b5f6b211..17189ae0f 100644 --- a/nuttx/net/net_sendfile.c +++ b/nuttx/net/net_sendfile.c @@ -170,11 +170,17 @@ static uint16_t ack_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn, dev->d_sndlen = 0; - /* Wake up the waiting thread */ + flags &= ~UIP_ACKDATA; + } + else if ((flags & UIP_REXMIT) != 0) + { + nlldbg("REXMIT\n"); - sem_post(&pstate->snd_sem); + /* Yes.. in this case, reset the number of bytes that have been sent + * to the number of bytes that have been ACKed. + */ - flags &= ~UIP_ACKDATA; + pstate->snd_sent = pstate->snd_acked; } /* Check for a loss of connection */ @@ -187,10 +193,12 @@ static uint16_t ack_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn, net_lostconnection(pstate->snd_sock, flags); pstate->snd_sent = -ENOTCONN; - - sem_post(&pstate->snd_sem); } + /* Wake up the waiting thread */ + + sem_post(&pstate->snd_sem); + return flags; } @@ -224,20 +232,9 @@ static uint16_t sendfile_interrupt(FAR struct uip_driver_s *dev, FAR void *pvcon nllvdbg("flags: %04x acked: %d sent: %d\n", flags, pstate->snd_acked, pstate->snd_sent); - if ((flags & UIP_REXMIT) != 0) - { - /* Yes.. in this case, reset the number of bytes that have been sent - * to the number of bytes that have been ACKed. - */ - - pstate->snd_sent = pstate->snd_acked; - - /* Fall through to re-send data from the last that was ACKed */ - } - /* Check for a loss of connection */ - else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) + if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) { /* Report not connected */ @@ -356,6 +353,14 @@ static uint16_t sendfile_interrupt(FAR struct uip_driver_s *dev, FAR void *pvcon } #endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ + if (pstate->snd_sent >= pstate->snd_flen + && pstate->snd_acked < pstate->snd_flen) + { + /* All data has been sent, but there are outstanding ACK's */ + + goto wait; + } + end_wait: /* Do not allow any further callbacks */ @@ -521,7 +526,7 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset, /* Set up the ACK callback in the connection */ - state.snd_ackcb->flags = UIP_ACKDATA|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; + state.snd_ackcb->flags = UIP_ACKDATA|UIP_REXMIT|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; state.snd_ackcb->priv = (void*)&state; state.snd_ackcb->event = ack_interrupt; @@ -529,7 +534,7 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset, do { - state.snd_datacb->flags = UIP_REXMIT|UIP_POLL; + state.snd_datacb->flags = UIP_POLL; state.snd_datacb->priv = (void*)&state; state.snd_datacb->event = sendfile_interrupt; @@ -539,7 +544,7 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset, uip_lockedwait(&state.snd_sem); } - while (state.snd_sent > 0 && state.snd_acked < state.snd_flen); + while (state.snd_sent >= 0 && state.snd_acked < state.snd_flen); /* Set the socket state to idle */ -- cgit v1.2.3