summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-11-24 13:02:03 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-11-24 13:02:03 +0000
commitb1ba6835d554382c77a216a3f2eb3fa7ded96535 (patch)
tree56a36463d7910eef8ea347271ce8bdaf582a23f7
parent2937aaaaf09c2f0d5b46b1a2a30eac962d8455d3 (diff)
downloadnuttx-b1ba6835d554382c77a216a3f2eb3fa7ded96535.tar.gz
nuttx-b1ba6835d554382c77a216a3f2eb3fa7ded96535.tar.bz2
nuttx-b1ba6835d554382c77a216a3f2eb3fa7ded96535.zip
Must disconnect TCP socket on close()
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@405 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/Documentation/NuttX.html4
-rw-r--r--nuttx/TODO1
-rw-r--r--nuttx/net/connect.c6
-rw-r--r--nuttx/net/net-close.c143
-rw-r--r--nuttx/net/sendto.c4
6 files changed, 150 insertions, 10 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index c498961db..58a7d7881 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -248,3 +248,5 @@
* Removed unused uIP files
* sched/, mm/, net/ subystem debug can not be selectively enabled/disabled
+ * Correct socket close logic -- needs to disconnect TCP socket on close
+ * uIP webserver now seems to be fully functional
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index 3b9d5ad10..969f78cd6 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
- <p>Last Updated: November 23, 2007</p>
+ <p>Last Updated: November 24, 2007</p>
</td>
</tr>
</table>
@@ -728,6 +728,8 @@ Other memory:
* Removed unused uIP files
* sched/, mm/, net/ subystem debug can not be selectively enabled/disabled
+ * Correct socket close logic -- needs to disconnect TCP socket on close
+ * uIP webserver now seems to be fully functional
</pre></ul>
<table width ="100%">
diff --git a/nuttx/TODO b/nuttx/TODO
index 8cc39d820..a9f96642c 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -33,7 +33,6 @@ o Network
but is not implemented.
- uIP's netutils/telnetd (and maybe others) are seriously broken.
Need to be re-written to use listen() and accept()
-- uIP's netutils/webserver hangs (I think NuttX is not properly closing the connection)
- uIP's netutils/smtp, dpcpc, resolv, webclient -- untested
- Should implement SOCK_RAW
- Performance Improvements (uIP is not very fast):
diff --git a/nuttx/net/connect.c b/nuttx/net/connect.c
index c6faa9e73..2316e1ba3 100644
--- a/nuttx/net/connect.c
+++ b/nuttx/net/connect.c
@@ -47,6 +47,7 @@
#include <debug.h>
#include <arch/irq.h>
+#include <net/uip/uip-arch.h>
#include "net-internal.h"
@@ -257,7 +258,10 @@ static uint8 tcp_connect_interrupt(struct uip_driver_s *dev,
else
{
- return 0;
+ /* Drop data received in this state */
+
+ dev->d_len = 0;
+ return flags & ~UIP_NEWDATA;
}
nvdbg("Resuming: %d\n", pstate->tc_result);
diff --git a/nuttx/net/net-close.c b/nuttx/net/net-close.c
index 76dd7693f..24a526ba6 100644
--- a/nuttx/net/net-close.c
+++ b/nuttx/net/net-close.c
@@ -42,12 +42,144 @@
#include <sys/types.h>
#include <sys/socket.h>
+
#include <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+#include <net/uip/uip-arch.h>
#include "net-internal.h"
/****************************************************************************
- * Global Functions
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP
+struct tcp_close_s
+{
+ FAR struct socket *cl_psock; /* Reference to the TCP socket */
+ sem_t cl_sem; /* Semaphore signals disconnect completion */
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: netclose_disconnect
+ *
+ * Description:
+ * Break any current TCP connection
+ *
+ * Parameters:
+ * conn - uIP TCP connection structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Called from normal user-level logic
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP
+static uint8 netclose_interrupt(struct uip_driver_s *dev,
+ struct uip_conn *conn, uint8 flags)
+{
+ struct tcp_close_s *pstate = (struct tcp_close_s *)conn->data_private;
+
+ nvdbg("flags: %02x\n", flags);
+
+ if (pstate)
+ {
+ /* UIP_CLOSE: The remote host has closed the connection
+ * UIP_ABORT: The remote host has aborted the connection
+ */
+
+ if ((flags & (UIP_CLOSE|UIP_ABORT)) != 0)
+ {
+ /* The disconnection is complete */
+
+ conn->data_private = NULL;
+ conn->data_event = NULL;
+ sem_post(&pstate->cl_sem);
+ nvdbg("Resuming\n");
+ }
+ else
+ {
+ /* Drop data received in this state and make sure that UIP_CLOSE
+ * is set in the response
+ */
+
+ dev->d_len = 0;
+ return (flags & ~UIP_NEWDATA) | UIP_CLOSE;
+ }
+ }
+
+ return flags;
+}
+#endif /* CONFIG_NET_TCP */
+
+/****************************************************************************
+ * Function: netclose_disconnect
+ *
+ * Description:
+ * Break any current TCP connection
+ *
+ * Parameters:
+ * conn - uIP TCP connection structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Called from normal user-level logic
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP
+static inline void netclose_disconnect(FAR struct socket *psock)
+{
+ struct tcp_close_s state;
+ struct uip_conn *conn;
+ irqstate_t flags;
+
+ /* Interrupts are disabled here to avoid race conditions */
+
+ flags = irqsave();
+
+ /* Is the TCP socket in a connected state? */
+
+ if (_SS_ISCONNECTED(psock->s_flags))
+ {
+ /* Set up to receive TCP data events */
+
+ state.cl_psock = psock;
+ sem_init(&state.cl_sem, 0, 0);
+
+ conn = psock->s_conn;
+ conn->data_private = (void*)&state;
+ conn->data_event = netclose_interrupt;
+
+ /* Wait for the disconnect event */
+
+ (void)sem_wait(&state.cl_sem);
+
+ /* We are now disconnected */
+
+ sem_destroy(&state.cl_sem);
+ conn->data_private = NULL;
+ conn->data_event = NULL;
+ }
+
+ irqrestore(flags);
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
****************************************************************************/
/****************************************************************************
@@ -87,20 +219,21 @@ int net_close(int sockfd)
case SOCK_STREAM:
{
struct uip_conn *conn = psock->s_conn;
- uip_unlisten(conn);
- uip_tcpfree(conn);
+ uip_unlisten(conn); /* No longer accepting connections */
+ netclose_disconnect(psock); /* Break any current connections */
+ uip_tcpfree(conn); /* Free uIP resources */
}
break;
#endif
#ifdef CONFIG_NET_UDP
case SOCK_DGRAM:
- uip_udpfree(psock->s_conn);
+ uip_udpfree(psock->s_conn); /* Free uIP resources */
break;
#endif
default:
- err = -EBADF;
+ err = EBADF;
goto errout;
}
diff --git a/nuttx/net/sendto.c b/nuttx/net/sendto.c
index ba9bac0af..a0f3cc4a1 100644
--- a/nuttx/net/sendto.c
+++ b/nuttx/net/sendto.c
@@ -196,18 +196,18 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
{
FAR struct socket *psock;
+#ifdef CONFIG_NET_UDP
#ifdef CONFIG_NET_IPv6
FAR const struct sockaddr_in6 *into = (const struct sockaddr_in6 *)to;
#else
FAR const struct sockaddr_in *into = (const struct sockaddr_in *)to;
#endif
-#ifdef CONFIG_NET_UDP
struct uip_udp_conn *udp_conn;
struct sendto_s state;
irqstate_t save;
+ int ret;
#endif
int err;
- int ret;
/* If to is NULL or tolen is zero, then this function is same as send (for
* connected socket types)