diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-11-24 13:02:03 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-11-24 13:02:03 +0000 |
commit | b1ba6835d554382c77a216a3f2eb3fa7ded96535 (patch) | |
tree | 56a36463d7910eef8ea347271ce8bdaf582a23f7 /nuttx/net/net-close.c | |
parent | 2937aaaaf09c2f0d5b46b1a2a30eac962d8455d3 (diff) | |
download | px4-nuttx-b1ba6835d554382c77a216a3f2eb3fa7ded96535.tar.gz px4-nuttx-b1ba6835d554382c77a216a3f2eb3fa7ded96535.tar.bz2 px4-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
Diffstat (limited to 'nuttx/net/net-close.c')
-rw-r--r-- | nuttx/net/net-close.c | 143 |
1 files changed, 138 insertions, 5 deletions
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; } |