summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/ChangeLog1
-rw-r--r--nuttx/Documentation/NuttX.html1
-rw-r--r--nuttx/TODO7
-rw-r--r--nuttx/net/accept.c7
-rw-r--r--nuttx/net/send.c114
5 files changed, 92 insertions, 38 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 9c9386b0c..05b8b3f1a 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -265,3 +265,4 @@
* Fix UDP recvfrom timeout bug
* Correct processing of input UDP broadcast packets.
* Verfied basic DHCP client functionality (netutils/dhcpc)
+ * Implemented send() timeout logic
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index e6fd36bdd..a0546ee63 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -753,6 +753,7 @@ Other memory:
* Fix UDP recvfrom timeout bug
* Correct processing of input UDP broadcast packets.
* Verfied basic DHCP client functionality (netutils/dhcpc)
+ * Implemented send() timeout logic
</pre></ul>
<table width ="100%">
diff --git a/nuttx/TODO b/nuttx/TODO
index 500013d14..a41b5f59d 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -29,10 +29,8 @@ o C++ Support
- Need to call static constructors
o Network
-- Did not implement send() and sendto() timeouts. Option is setable via setsockopt,
- but is not implemented.
-- uIP's netutils/smtp, dpcpc, resolv, webclient -- untested
-- Should implement SOCK_RAW
+- uIP's netutils/smtp, resolv, webclient -- untested
+- Should implement SOCK_RAW, SOCK_PACKET
- uIP polling issues:
(1) Current logic will not support multiple ethernet drivers. Each driver should
poll on TCP connections connect on the network supported by the driver; UDP
@@ -44,6 +42,7 @@ o Network
- uIP/Socket callback logic is not thread safe. This means that a socket cannot be
used concurrently by two threads. Minimal fix: Add mutex to support exclusion.
- IPv6 support is incomplete
+- Incoming UDP broadcast should only be accepted if listening on INADDR_ANY(?)
o USB
- Implement USB device support
diff --git a/nuttx/net/accept.c b/nuttx/net/accept.c
index 8c32eac3a..0541fa061 100644
--- a/nuttx/net/accept.c
+++ b/nuttx/net/accept.c
@@ -111,12 +111,7 @@ static inline void accept_tcpsender(struct uip_conn *conn, struct accept_s *psta
{
addr->sin_family = AF_INET;
addr->sin_port = conn->rport;
-
-#ifdef CONFIG_NET_IPv6
uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr);
-#else
- uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr);
-#endif
}
}
#endif
@@ -400,4 +395,4 @@ errout:
return ERROR;
}
-#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP*/
+#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP */
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index 67acc6285..15a7adc0b 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -75,6 +75,9 @@ struct send_s
ssize_t snd_sent; /* The number of bytes sent */
uint32 snd_isn; /* Initial sequence number */
uint32 snd_acked; /* The number of bytes acked */
+#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
+ uint32 snd_time; /* last send time for determining timeout */
+#endif
};
/****************************************************************************
@@ -130,6 +133,46 @@ static uint32 send_getackno(struct uip_driver_s *dev)
}
/****************************************************************************
+ * Function: send_timeout
+ *
+ * Description:
+ * Check for send timeout.
+ *
+ * Parameters:
+ * pstate send state structure
+ *
+ * Returned Value:
+ * TRUE:timeout FALSE:no timeout
+ *
+ * Assumptions:
+ * Running at the interrupt level
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
+static inline int send_timeout(struct send_s *pstate)
+{
+ FAR struct socket *psock = 0;
+
+ /* Check for a timeout configured via setsockopts(SO_SNDTIMEO).
+ * If none... we well let the send wait forever.
+ */
+
+ psock = pstate->snd_sock;
+ if (psock && psock->s_sndtimeo != 0)
+ {
+ /* Check if the configured timeout has elapsed */
+
+ return net_timeo(pstate->snd_time, psock->s_sndtimeo);
+ }
+
+ /* No timeout */
+
+ return FALSE;
+}
+#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
+
+/****************************************************************************
* Function: send_interrupt
*
* Description:
@@ -149,7 +192,8 @@ static uint32 send_getackno(struct uip_driver_s *dev)
*
****************************************************************************/
-static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
+static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn,
+ uint8 flags)
{
struct send_s *pstate = (struct send_s *)conn->data_private;
@@ -161,10 +205,10 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
if ((flags & UIP_ACKDATA) != 0)
{
- /* The current acknowledgement number number is the (relative) offset of
- * the of the next byte needed by the receiver. The snd_isn is the offset
- * of the first byte to send to the receiver. The difference is the number
- * of bytes to be acknowledged.
+ /* The current acknowledgement number number is the (relative) offset
+ * of the of the next byte needed by the receiver. The snd_isn is the
+ * offset of the first byte to send to the receiver. The difference
+ * is the number of bytes to be acknowledged.
*/
pstate->snd_acked = send_getackno(dev) - pstate->snd_isn;
@@ -175,23 +219,14 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
if ( pstate->snd_acked >= pstate->snd_buflen)
{
- /* Yes. Then pstate->snd_len should hold the number of bytes actually
- * sent.
- *
- * Don't allow any further call backs.
- */
-
- conn->data_flags = 0;
- conn->data_private = NULL;
- conn->data_event = NULL;
-
- /* Wake up the waiting thread, returning the number of bytes
+ /* Yes. Then pstate->snd_len should hold the number of bytes
* actually sent.
*/
- sem_post(&pstate->snd_sem);
- return flags;
+ goto end_wait;
}
+
+ /* No.. fall through to send more data if necessary */
}
/* Check if we are being asked to retransmit data */
@@ -203,25 +238,19 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
*/
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)
{
- /* Stop further callbacks */
-
- conn->data_flags = 0;
- conn->data_private = NULL;
- conn->data_event = NULL;
-
/* Report not connected */
+ nvdbg("Lost connection\n");
pstate->snd_sent = -ENOTCONN;
-
- /* Wake up the waiting thread */
-
- sem_post(&pstate->snd_sem);
+ goto end_wait;
}
/* We get here if (1) not all of the data has been ACKed, (2) we have been
@@ -250,6 +279,35 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
}
+ /* All data has been send and we are just waiting for ACK or re-tranmist
+ * indications to complete the send. Check for a timeout.
+ */
+
+#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
+ else if (send_timeout(pstate))
+ {
+ /* Yes.. report the timeout */
+
+ nvdbg("TCP timeout\n");
+ pstate->snd_sent = -EAGAIN;
+ goto end_wait;
+ }
+#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
+
+ /* Continue waiting */
+
+ return flags;
+
+end_wait:
+ /* Do not allow any further callbacks */
+
+ conn->data_flags = 0;
+ conn->data_private = NULL;
+ conn->data_event = NULL;
+
+ /* Wake up the waiting thread */
+
+ sem_post(&pstate->snd_sem);
return flags;
}