diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-18 17:30:30 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-18 17:30:30 +0000 |
commit | 1994f6983332bf79b4ea8d3f242dc710f99cf2e9 (patch) | |
tree | 414ecfd618101a507bf1b3c9263cd067b2ad7b9b /nuttx/net/net-poll.c | |
parent | 3a3f46b691da1747881032dec6f5b5af2c308cdd (diff) | |
download | px4-nuttx-1994f6983332bf79b4ea8d3f242dc710f99cf2e9.tar.gz px4-nuttx-1994f6983332bf79b4ea8d3f242dc710f99cf2e9.tar.bz2 px4-nuttx-1994f6983332bf79b4ea8d3f242dc710f99cf2e9.zip |
Implement poll/select for sockets
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1277 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/net/net-poll.c')
-rw-r--r-- | nuttx/net/net-poll.c | 292 |
1 files changed, 284 insertions, 8 deletions
diff --git a/nuttx/net/net-poll.c b/nuttx/net/net-poll.c index b11cfe964..08c2bb1b4 100644 --- a/nuttx/net/net-poll.c +++ b/nuttx/net/net-poll.c @@ -49,7 +49,231 @@ #include "net-internal.h" /**************************************************************************** - * Global Functions + * Pre-processor Definitions + ****************************************************************************/ + +/* Network polling can only be supported on TCP and only if read-ahead buffering + * is enabled (it could be supported on UDP as will if it also had read-ahead + * buffering. + */ + +#if defined(CONFIG_DISABLE_POLL) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \ + defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +# define HAVE_NETPOLL 1 +#else +# undef HAVE_NETPOLL +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct net_poll_s +{ + FAR struct pollfd *fds; /* The descriptor poll info */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: poll_interrupt + * + * Description: + * This function is called from the interrupt level to perform the actual + * TCP receive operation via by the uIP layer. + * + * Parameters: + * dev The structure of the network driver that caused the interrupt + * conn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * None + * + * Assumptions: + * Running at the interrupt level + * + ****************************************************************************/ + +#ifdef HAVE_NETPOLL +static uint16 poll_interrupt(struct uip_driver_s *dev, FAR void *conn, + FAR void *pvprivate, uint16 flags) +{ + struct pollfd *fds = (struct recvfrom_s *)pvprivate; + + nvdbg("flags: %04x\n", flags); + + /* 'private' might be null in some race conditions (?) */ + + if (fds) + { + pollevent_t eventset = 0; + + /* Check for data availability events. */ + + if ((flags & UIP_NEWDATA) != 0) + { + eventset |= POLLIN & fds->events; + } + + /* A poll is a sign that we are free to send data. */ + + if ((flags & UIP_POLL) != 0) + { + eventset |= POLLOUT & fds->events; + } + + /* Check for a loss of connection events */ + + if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) + { + eventset |= (POLLERR|POLLHUP); + } + + if (eventset) + { + fds->revevents |= eventset; + sem_post(fds->sem); + } + } + return flags; +} +#endif /* HAVE_NETPOLL */ + +/**************************************************************************** + * Function: net_pollsetup + * + * Description: + * Setup to monitor events on one TCP/IP socket + * + * Input Parameters: + * conn - The TCP/IP connection of interest + * fds - The structure describing the events to be monitored, OR NULL if + * this is a request to stop monitoring events. + * + * Returned Value: + * 0: Success; Negated errno on failure + * + ****************************************************************************/ + +#ifdef HAVE_NETPOLL +static inline int net_pollsetup((FAR struct uip_conn *)conn, struct pollfd *fds) +{ + FAR struct uip_callback_s *cb; + irqstate_t flags; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!conn || !fds || fds->private) + { + ret = -EINVAL; + goto errout; + } +#endif + + /* Some of the following must be atomic */ + + flags = irqsave(); + + /* Allocate a TCP/IP callback structure */ + + cb = uip_tcpcallbackalloc(conn); + if (!cb) + { + ret = -EBUSY; + goto errout_with_irq; + } + + /* Initialize the callbcack structure */ + + cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; + cb->private = (FAR void *)fds; + cb->event = poll_interrupt; + + /* Save the nps reference in the poll structure for use at teardown as well */ + + fds->private = (FAR void *)cb; + + /* Check for read data availability now */ + + if (!sq_empty(&conn->readahead)) + { + fds->revents = fds->events & POLLIN; + if (fds->revents != 0) + { + /* If data is available now, the signal the poll logic */ + + sem_post(fds->sem); + } + } + irqrestore(flags); + return OK; + +errout_with_irq: + irqrestore(flags); + free(nps); +errout: + return ret; +} +#endif /* HAVE_NETPOLL */ + +/**************************************************************************** + * Function: net_pollteardown + * + * Description: + * Teardown monitoring of events on an TCP/IP socket + * + * Input Parameters: + * conn - The TCP/IP connection of interest + * + * Returned Value: + * 0: Success; Negated errno on failure + * + ****************************************************************************/ + +#ifdef HAVE_NETPOLL +static inline int net_pollteardown((FAR struct uip_conn *)conn, struct pollfd *fds) +{ + FAR struct uip_callback_s *cb; + irqstate_t flags; + int ret; + + /* Sanity check */ + +#ifdef CONFIG_DEBUG + if (!conn || !fds || !fds->private) + { + ret = -EINVAL; + goto errout; + } +#endif + + /* Recover the socket descriptor poll state info from the poll structure */ + + cb = (FAR struct uip_callback_s *)fds->private; + if (cb) + { + /* Release the callback */ + + flags = irqsave(); + uip_tcpcallbackfree(conn, cb); + irqrestore(flags); + + /* Release the poll/select data slot */ + + fds->private = NULL; + } + + return OK; +} +#endif /* HAVE_NETPOLL */ + +/**************************************************************************** + * Public Functions ****************************************************************************/ /**************************************************************************** @@ -59,22 +283,74 @@ * The standard poll() operation redirects operations on socket descriptors * to this function. * - * Parameters: + * Input Parameters: * fd - The socket descriptor of interest - * fds - The structures describing events to be monitored, OR NULL if + * fds - The structure describing the events to be monitored, OR NULL if * this is a request to stop monitoring events. * * Returned Value: - * TBD + * 0: Success; Negated errno on failure * ****************************************************************************/ +#ifndef CONFIG_DISABLE_POLL int net_poll(int sockfd, struct pollfd *fds) { -#ifdef CONFIG_CPP_HAVE_WARNING -# warning To be provided -#endif +#ifndef HAVE_NETPOLL return -ENOSYS; +#else + FAR struct socket *psock; + int ret; + + /* Verify that non-NULL pointers were passed */ + +#ifdef CONFIG_DEBUG + if (!fds) + { + ret = -EINVAL; + goto errout; + } +#endif + + /* Get the underlying socket structure and verify that the sockfd + * corresponds to valid, allocated socket + */ + + psock = sockfd_socket(sockfd); + if (!psock || psock->s_crefs <= 0) + { + ret = -EBADF; + goto errout; + } + +#ifdef CONFIG_NET_UDP + /* poll() not supported for UDP */ + + if (psock->s_type != SOCK_STREAM) + { + ret = -ENOSYS; + goto errout; + } +#endif + + /* Check if we are setting up or tearing down the poll */ + if (fds) + { + /* Perform the TCP/IP poll() setup */ + + ret = net_pollsetup((FAR struct uip_conn *)psock->conn, fds); + } + else + { + /* Perform the TCP/IP poll() teardown */ + + ret = net_pollteardown((FAR struct uip_conn *)psock->conn); + } + +errout: + return ret; +#endif /* HAVE_NETPOLL */ } +#endif /* !CONFIG_DISABLE_POLL */ -#endif /* CONFIG_NET&& !CONFIG_DISABLE_POLL */ +#endif /* CONFIG_NET && !CONFIG_DISABLE_POLL */ |