summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-10-17 09:54:48 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-10-17 09:54:48 -0600
commitcfbd603eeb19635d391dfafb74deb06611c9486a (patch)
treed0aa09490fa62801d1795ab53e18ee42baf97c01
parent60bff805a236dc7e599d546fd9cef04246bfc078 (diff)
downloadpx4-nuttx-cfbd603eeb19635d391dfafb74deb06611c9486a.tar.gz
px4-nuttx-cfbd603eeb19635d391dfafb74deb06611c9486a.tar.bz2
px4-nuttx-cfbd603eeb19635d391dfafb74deb06611c9486a.zip
net_sendfile: Let the ACK callback handle the REXMIT flag and don't return until all data has been ACK'd. From Max Holtzberg
-rw-r--r--nuttx/ChangeLog6
-rw-r--r--nuttx/net/net_sendfile.c45
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 */