diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-20 18:18:19 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-20 18:18:19 +0000 |
commit | eafaeb9398216dacb92de69683ccdda6007efb1d (patch) | |
tree | e513e4fd791670d9b74d33821682d4059ed73098 /apps/examples/poll | |
parent | f68c474e8ae9cfa5c9124a6eb92ec06fe2bf40a1 (diff) | |
download | nuttx-eafaeb9398216dacb92de69683ccdda6007efb1d.tar.gz nuttx-eafaeb9398216dacb92de69683ccdda6007efb1d.tar.bz2 nuttx-eafaeb9398216dacb92de69683ccdda6007efb1d.zip |
Move nuttx/examples to apps/examples
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3405 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/examples/poll')
-rw-r--r-- | apps/examples/poll/Makefile | 90 | ||||
-rw-r--r-- | apps/examples/poll/Makefile.host | 54 | ||||
-rw-r--r-- | apps/examples/poll/host.c | 166 | ||||
-rw-r--r-- | apps/examples/poll/net_listener.c | 428 | ||||
-rw-r--r-- | apps/examples/poll/net_reader.c | 317 | ||||
-rw-r--r-- | apps/examples/poll/poll_internal.h | 128 | ||||
-rw-r--r-- | apps/examples/poll/poll_listener.c | 262 | ||||
-rw-r--r-- | apps/examples/poll/poll_main.c | 229 | ||||
-rw-r--r-- | apps/examples/poll/select_listener.c | 193 |
9 files changed, 1867 insertions, 0 deletions
diff --git a/apps/examples/poll/Makefile b/apps/examples/poll/Makefile new file mode 100644 index 000000000..0bfc97ec1 --- /dev/null +++ b/apps/examples/poll/Makefile @@ -0,0 +1,90 @@ +############################################################################ +# apps/examples/poll/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Device Driver poll()/select() Example + +ASRCS = +CSRCS = poll_main.c poll_listener.c select_listener.c net_listener.c net_reader.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = ../../libapps$(LIBEXT) + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: .built clean depend disclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + @touch .built + +.built: $(BIN) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f $(BIN) *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend host + +-include Make.dep diff --git a/apps/examples/poll/Makefile.host b/apps/examples/poll/Makefile.host new file mode 100644 index 000000000..9d9daee27 --- /dev/null +++ b/apps/examples/poll/Makefile.host @@ -0,0 +1,54 @@ +############################################################################ +# apps/examples/poll/Makefile.host +# +# Copyright (C) 2008, 2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# TOPDIR must be defined on the make command line + +include $(TOPDIR)/.config +include $(TOPDIR)/Make.defs + +SRC = host.c +BIN = host + +DEFINES = -DTARGETIP=\"$(TARGETIP)\" + +all: $(BIN) + +$(BIN): $(SRC) + $(HOSTCC) $(HOSTCFLAGS) $(DEFINES) $^ -o $@ + +clean: + @rm -f $(BIN) *~ .*.swp *.o + $(call CLEAN) + diff --git a/apps/examples/poll/host.c b/apps/examples/poll/host.c new file mode 100644 index 000000000..47f2c3e53 --- /dev/null +++ b/apps/examples/poll/host.c @@ -0,0 +1,166 @@ +/**************************************************************************** + * examples/poll/host.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <sys/socket.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <errno.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#define pthread_addr_t void * +#include "poll_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef TARGETIP +# error TARGETIP not defined +#endif + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * main + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + struct sockaddr_in myaddr; + char outbuf[IOBUFFER_SIZE]; + char inbuf[IOBUFFER_SIZE]; + int sockfd; + int len; + int nbytessent; + int nbytesrecvd; + int i; + + /* Create a new TCP socket */ + + sockfd = socket(PF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + message("client socket failure %d\n", errno); + goto errout_with_outbufs; + } + + /* Connect the socket to the server */ + + myaddr.sin_family = AF_INET; + myaddr.sin_port = htons(LISTENER_PORT); + myaddr.sin_addr.s_addr = inet_addr(TARGETIP); + + message("client: Connecting to %s...\n", TARGETIP); + if (connect( sockfd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0) + { + message("client: connect failure: %d\n", errno); + goto errout_with_socket; + } + message("client: Connected\n"); + + /* Then send and receive messages */ + + for (i = 0; ; i++) + { + sprintf(outbuf, "Remote message %d", i); + len = strlen(outbuf); + + message("client: Sending '%s' (%d bytes)\n", outbuf, len); + nbytessent = send(sockfd, outbuf, len, 0); + message("client: Sent %d bytes\n", nbytessent); + + if (nbytessent < 0) + { + message("client: send failed: %d\n", errno); + goto errout_with_socket; + } + else if (nbytessent != len) + { + message("client: Bad send length: %d Expected: %d\n", nbytessent, len); + goto errout_with_socket; + } + + message("client: Receiving...\n"); + nbytesrecvd = recv(sockfd, inbuf, IOBUFFER_SIZE, 0); + + if (nbytesrecvd < 0) + { + message("client: recv failed: %d\n", errno); + goto errout_with_socket; + } + + inbuf[nbytesrecvd] = '\0'; + message("client: Received '%s' (%d bytes)\n", inbuf, nbytesrecvd); + + if (nbytesrecvd != len) + { + message("client: Bad recv length: %d Expected: %d\n", nbytesrecvd, len); + goto errout_with_socket; + } + else if (memcmp(inbuf, outbuf, len) != 0) + { + message("client: Received outbuf does not match sent outbuf\n"); + goto errout_with_socket; + } + + message("client: Sleeping\n"); + sleep(8); + } + + close(sockfd); + return 0; + +errout_with_socket: + close(sockfd); +errout_with_outbufs: + exit(1); +} diff --git a/apps/examples/poll/net_listener.c b/apps/examples/poll/net_listener.c new file mode 100644 index 000000000..4d425c608 --- /dev/null +++ b/apps/examples/poll/net_listener.c @@ -0,0 +1,428 @@ +/**************************************************************************** + * examples/poll/net_listener.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/ioctl.h> + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <errno.h> +#include <debug.h> + +#include <net/if.h> +#include <apps/netutils/uiplib.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct net_listener_s +{ + struct sockaddr_in addr; + fd_set master; + fd_set working; + char buffer[IOBUFFER_SIZE]; + int listensd; + int mxsd; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_closeclient + ****************************************************************************/ + +static bool net_closeclient(struct net_listener_s *nls, int sd) +{ + message("net_listener: Closing host side connection sd=%d\n", sd); + close(sd); + FD_CLR(sd, &nls->master); + + /* If we just closed the max SD, then search downward for the next biggest SD. */ + + while (FD_ISSET(nls->mxsd, &nls->master) == false) + { + nls->mxsd -= 1; + } + return true; +} + +/**************************************************************************** + * Name: net_incomingdata + ****************************************************************************/ + +static inline bool net_incomingdata(struct net_listener_s *nls, int sd) +{ + char *ptr; + int nbytes; + int ret; + + /* Read data from the socket */ + +#ifdef FIONBIO + for (;;) +#endif + { + message("net_listener: Read data from sd=%d\n", sd); + ret = recv(sd, nls->buffer, IOBUFFER_SIZE, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_listener: recv failed sd=%d: %d\n", sd, errno); + if (errno != EAGAIN) + { + net_closeclient(nls, sd); + return false; + } + } + } + else if (ret == 0) + { + message("net_listener: Client connection lost sd=%d\n", sd); + net_closeclient(nls, sd); + return false; + } + else + { + nls->buffer[ret]='\0'; + message("poll_listener: Read '%s' (%d bytes)\n", nls->buffer, ret); + + /* Echo the data back to the client */ + + for (nbytes = ret, ptr = nls->buffer; nbytes > 0; ) + { + ret = send(sd, ptr, nbytes, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_listener: Send failed sd=%d: \n", sd, errno); + net_closeclient(nls, sd); + return false; + } + } + else + { + nbytes -= ret; + ptr += ret; + } + } + } + } + return 0; +} + +/**************************************************************************** + * Name: net_connection + ****************************************************************************/ + +static inline bool net_connection(struct net_listener_s *nls) +{ + int sd; + + /* Loop until all connections have been processed */ + +#ifdef FIONBIO + for (;;) +#endif + { + message("net_listener: Accepting new connection on sd=%d\n", nls->listensd); + + sd = accept(nls->listensd, NULL, NULL); + if (sd < 0) + { + message("net_listener: accept failed: %d\n", errno); + + if (errno != EINTR) + { + return false; + } + } + else + { + /* Add the new connection to the master set */ + + message("net_listener: Connection accepted for sd=%d\n", sd); + + FD_SET(sd, &nls->master); + if (sd > nls->mxsd) + { + nls->mxsd = sd; + } + return true; + } + } + return false; +} + +/**************************************************************************** + * Name: net_mksocket + ****************************************************************************/ + +static inline bool net_mksocket(struct net_listener_s *nls) +{ + int value; + int ret; + + /* Create a listening socket */ + + message("net_listener: Initializing listener socket\n"); + nls->listensd = socket(AF_INET, SOCK_STREAM, 0); + if (nls->listensd < 0) + { + message("net_listener: socket failed: %d\n", errno); + return false; + } + + /* Configure the socket */ + + value = 1; + ret = setsockopt(nls->listensd, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(int)); + if (ret < 0) + { + message("net_listener: setsockopt failed: %d\n", errno); + close(nls->listensd); + return false; + } + + /* Set the socket to non-blocking */ + +#ifdef FIONBIO + ret = ioctl(nls->listensd, FIONBIO, (char *)&value); + if (ret < 0) + { + message("net_listener: ioctl failed: %d\n", errno); + close(nls->listensd); + return false; + } +#endif + + /* Bind the socket */ + + memset(&nls->addr, 0, sizeof(struct sockaddr_in)); + nls->addr.sin_family = AF_INET; + nls->addr.sin_addr.s_addr = htonl(INADDR_ANY); + nls->addr.sin_port = htons(LISTENER_PORT); + ret = bind(nls->listensd, (struct sockaddr *)&nls->addr, sizeof(struct sockaddr_in)); + if (ret < 0) + { + message("net_listener: bind failed: %d\n", errno); + close(nls->listensd); + return false; + } + + /* Mark the socket as a listener */ + + ret = listen(nls->listensd, 32); + if (ret < 0) + { + message("net_listener: bind failed: %d\n", errno); + close(nls->listensd); + return false; + } + + return true; +} + +/**************************************************************************** + * Name: net_configure + ****************************************************************************/ + +static void net_configure(void) +{ + struct in_addr addr; +#if defined(CONFIG_EXAMPLE_POLL_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif + + /* Configure uIP */ + /* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLE_POLL_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xb0; + mac[3] = 0x0b; + mac[4] = 0xba; + mac[5] = 0xbe; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + uip_setnetmask("eth0", &addr); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_listener + ****************************************************************************/ + +void *net_listener(pthread_addr_t pvarg) +{ + struct net_listener_s nls; + struct timeval timeout; + int nsds; + int ret; + int i; + + /* Configure uIP */ + + net_configure(); + + /* Set up a listening socket */ + + memset(&nls, 0, sizeof(struct net_listener_s)); + if (!net_mksocket(&nls)) + { + return (void*)1; + } + + /* Initialize the 'master' file descriptor set */ + + FD_ZERO(&nls.master); + nls.mxsd = nls.listensd; + FD_SET(nls.listensd, &nls.master); + + /* Set up a 3 second timeout */ + + timeout.tv_sec = NET_LISTENER_DELAY; + timeout.tv_usec = 0; + + /* Loop waiting for incoming connections or for incoming data + * on any of the connect sockets. + */ + + for (;;) + { + /* Wait on select */ + + message("net_listener: Calling select(), listener sd=%d\n", nls.listensd); + memcpy(&nls.working, &nls.master, sizeof(fd_set)); + ret = select(nls.mxsd + 1, (FAR fd_set*)&nls.working, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout); + if (ret < 0) + { + message("net_listener: select failed: %d\n", errno); + break; + } + + /* Check for timeout */ + + if (ret == 0) + { + message("net_listener: Timeout\n"); + continue; + } + + /* Find which descriptors caused the wakeup */ + + nsds = ret; + for (i = 0; i <= nls.mxsd && nsds > 0; i++) + { + /* Is this descriptor ready? */ + + if (FD_ISSET(i, &nls.working)) + { + /* Yes, is it our listener? */ + + message("net_listener: Activity on sd=%d\n", i); + + nsds--; + if (i == nls.listensd) + { + (void)net_connection(&nls); + } + else + { + net_incomingdata(&nls, i); + } + } + } + } + + /* Cleanup */ + +#if 0 /* Don't get here */ + for (i = 0; i <= nls.mxsd; +i++) + { + if (FD_ISSET(i, &nls.master)) + { + close(i); + } + } +#endif + return NULL; /* Keeps some compilers from complaining */ +} diff --git a/apps/examples/poll/net_reader.c b/apps/examples/poll/net_reader.c new file mode 100644 index 000000000..b0cf94316 --- /dev/null +++ b/apps/examples/poll/net_reader.c @@ -0,0 +1,317 @@ +/**************************************************************************** + * examples/poll/net_reader.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/socket.h> + +#include <stdint.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include <net/if.h> +#include <apps/netutils/uiplib.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_configure + ****************************************************************************/ + +static void net_configure(void) +{ + struct in_addr addr; +#if defined(CONFIG_EXAMPLE_POLL_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif + + /* Configure uIP */ + /* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLE_POLL_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xb0; + mac[3] = 0x0b; + mac[4] = 0xba; + mac[5] = 0xbe; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + uip_setnetmask("eth0", &addr); +} + +/**************************************************************************** + * Name: net_receive + ****************************************************************************/ + +static void net_receive(int sd) +{ + struct timeval timeout; + char buffer[IOBUFFER_SIZE]; + char *ptr; + fd_set readset; + int nbytes; + int ret; + + /* Set up the timeout */ + + timeout.tv_sec = NET_LISTENER_DELAY; + timeout.tv_usec = 0; + + /* Loop while we have the connection */ + + for (;;) + { + /* Wait for incoming message */ + + do + { + FD_ZERO(&readset); + FD_SET(sd, &readset); + ret = select(sd + 1, (FAR fd_set*)&readset, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout); + } + while (ret < 0 && errno == EINTR); + + /* Something has happened */ + + if (ret < 0) + { + message("net_reader: select failed: %d\n", errno); + return; + } + else if (ret == 0) + { + message("net_reader: Timeout\n"); + } + else + { + message("net_reader: Read data from sd=%d\n", sd); + memset(buffer, '?', IOBUFFER_SIZE); /* Just to make sure we really receive something */ + ret = recv(sd, buffer, IOBUFFER_SIZE, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_reader: recv failed sd=%d: %d\n", sd, errno); + if (errno != EAGAIN) + { + return; + } + } + } + else if (ret == 0) + { + message("net_reader: Client connection lost sd=%d\n", sd); + return; + } + else + { + buffer[ret]='\0'; + message("net_reader: Read '%s' (%d bytes)\n", buffer, ret); + + /* Echo the data back to the client */ + + for (nbytes = ret, ptr = buffer; nbytes > 0; ) + { + ret = send(sd, ptr, nbytes, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_reader: Send failed sd=%d: %d\n", sd, errno); + return; + } + } + else + { + nbytes -= ret; + ptr += ret; + } + } + } + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_reader + ****************************************************************************/ + +void *net_reader(pthread_addr_t pvarg) +{ + struct sockaddr_in addr; +#ifdef POLL_HAVE_SOLINGER + struct linger ling; +#endif + int listensd; + int acceptsd; + socklen_t addrlen; + int optval; + + /* Configure uIP */ + + net_configure(); + + /* Create a new TCP socket */ + + listensd = socket(PF_INET, SOCK_STREAM, 0); + if (listensd < 0) + { + message("net_reader: socket failure: %d\n", errno); + goto errout; + } + + /* Set socket to reuse address */ + + optval = 1; + if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) + { + message("net_reader: setsockopt SO_REUSEADDR failure: %d\n", errno); + goto errout_with_listensd; + } + + /* Bind the socket to a local address */ + + addr.sin_family = AF_INET; + addr.sin_port = HTONS(LISTENER_PORT); + addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(listensd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) + { + message("net_reader: bind failure: %d\n", errno); + goto errout_with_listensd; + } + + /* Listen for connections on the bound TCP socket */ + + if (listen(listensd, 5) < 0) + { + message("net_reader: listen failure %d\n", errno); + goto errout_with_listensd; + } + + /* Connection loop */ + + for (;;) + { + /* Accept only one connection */ + + message("net_reader: Accepting new connections on port %d\n", LISTENER_PORT); + addrlen = sizeof(struct sockaddr_in); + acceptsd = accept(listensd, (struct sockaddr*)&addr, &addrlen); + if (acceptsd < 0) + { + message("net_reader: accept failure: %d\n", errno); + continue; + } + message("net_reader: Connection accepted on sd=%d\n", acceptsd); + + /* Configure to "linger" until all data is sent when the socket is closed */ + +#ifdef POLL_HAVE_SOLINGER + ling.l_onoff = 1; + ling.l_linger = 30; /* timeout is seconds */ + if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0) + { + message("net_reader: setsockopt SO_LINGER failure: %d\n", errno); + goto errout_with_acceptsd; + } +#endif + + /* Handle incoming messsages on the connection. */ + + net_receive(acceptsd); + + message("net_reader: Closing sd=%d\n", acceptsd); + close(acceptsd); + } + +#ifdef POLL_HAVE_SOLINGER +errout_with_acceptsd: + close(acceptsd); +#endif +errout_with_listensd: + close(listensd); +errout: + return NULL; +} diff --git a/apps/examples/poll/poll_internal.h b/apps/examples/poll/poll_internal.h new file mode 100644 index 000000000..cbf42ac56 --- /dev/null +++ b/apps/examples/poll/poll_internal.h @@ -0,0 +1,128 @@ +/**************************************************************************** + * examples/poll/poll_internal.h + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __EXAMPLES_PIPE_PIPE_H +#define __EXAMPLES_PIPE_PIPE_H + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <pthread.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_DISABLE_POLL +# error "The polling API is disabled" +#endif + +/* Here are all of the configuration settings that must be met to have TCP/IP + * poll/select support. This kind of looks like overkill. + * + * CONFIG_NET - Network support must be enabled + * CONFIG_NSOCKET_DESCRIPTORS - Socket descriptors must be allocated + * CONFIG_NET_TCP - Only support on TCP (because read-ahead + * ibuffering s not yet support for UDP) + * CONFIG_NET_NTCP_READAHEAD_BUFFERS - TCP/IP read-ahead buffering must be enabled + */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \ + defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +# define HAVE_NETPOLL 1 +#else +# undef HAVE_NETPOLL +#endif + +/* If debug is enabled, then use lib_rawprintf so that OS debug output and + * the test output are synchronized. + * + * These macros will differ depending upon if the toolchain supports + * macros with a variable number of arguments or not. + */ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_rawprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_rawprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +#define FIFO_PATH1 "/dev/fifo0" +#define FIFO_PATH2 "/dev/fifo1" + +#define POLL_LISTENER_DELAY 2000 /* 2 seconds */ +#define SELECT_LISTENER_DELAY 4 /* 4 seconds */ +#define NET_LISTENER_DELAY 3 /* 3 seconds */ +#define WRITER_DELAY 6 /* 6 seconds */ + +#define LISTENER_PORT 5471 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern void *poll_listener(pthread_addr_t pvarg); +extern void *select_listener(pthread_addr_t pvarg); + +#ifdef HAVE_NETPOLL +extern void *net_listener(pthread_addr_t pvarg); +extern void *net_reader(pthread_addr_t pvarg); +#endif +#endif /* __EXAMPLES_PIPE_PIPE_H */ diff --git a/apps/examples/poll/poll_listener.c b/apps/examples/poll/poll_listener.c new file mode 100644 index 000000000..816647e34 --- /dev/null +++ b/apps/examples/poll/poll_listener.c @@ -0,0 +1,262 @@ +/**************************************************************************** + * examples/poll/poll_listener.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <poll.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#if defined(CONFIG_DEV_CONSOLE) && !defined(CONFIG_DEV_LOWCONSOLE) +# define HAVE_CONSOLE +# define NPOLLFDS 2 +# define CONSNDX 0 +# define FIFONDX 1 +#else +# undef HAVE_CONSOLE +# define NPOLLFDS 1 +# define FIFONDX 0 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: poll_listener + ****************************************************************************/ + +void *poll_listener(pthread_addr_t pvarg) +{ + struct pollfd fds[NPOLLFDS]; + char buffer[64]; + ssize_t nbytes; + bool timeout; + bool pollin; + int nevents; + int fd; + int ret; + int i; + + /* Open the FIFO for non-blocking read */ + + message("poll_listener: Opening %s for non-blocking read\n", FIFO_PATH1); + fd = open(FIFO_PATH1, O_RDONLY|O_NONBLOCK); + if (fd < 0) + { + message("poll_listener: ERROR Failed to open FIFO %s: %d\n", + FIFO_PATH1, errno); + (void)close(fd); + return (void*)-1; + } + + /* Loop forever */ + + for (;;) + { + message("poll_listener: Calling poll()\n"); + + memset(fds, 0, sizeof(struct pollfd)*NPOLLFDS); +#ifdef HAVE_CONSOLE + fds[CONSNDX].fd = 0; + fds[CONSNDX].events = POLLIN; + fds[CONSNDX].revents = 0; +#endif + fds[FIFONDX].fd = fd; + fds[FIFONDX].events = POLLIN; + fds[FIFONDX].revents = 0; + + timeout = false; + pollin = false; + + ret = poll(fds, NPOLLFDS, POLL_LISTENER_DELAY); + + message("\npoll_listener: poll returned: %d\n", ret); + if (ret < 0) + { + message("poll_listener: ERROR poll failed: %d\n", errno); + } + else if (ret == 0) + { + message("poll_listener: Timeout\n"); + timeout = true; + } + else if (ret > NPOLLFDS) + { + message("poll_listener: ERROR poll reported: %d\n"); + } + else + { + pollin = true; + } + + nevents = 0; + for (i = 0; i < NPOLLFDS; i++) + { + message("poll_listener: FIFO revents[%d]=%02x\n", i, fds[i].revents); + if (timeout) + { + if (fds[i].revents != 0) + { + message("poll_listener: ERROR? expected revents=00, received revents[%d]=%02x\n", + fds[i].revents, i); + } + } + else if (pollin) + { + if (fds[i].revents == POLLIN) + { + nevents++; + } + else if (fds[i].revents != 0) + { + message("poll_listener: ERROR unexpected revents[i]=%02x\n", + i, fds[i].revents); + } + } + } + + if (pollin && nevents != ret) + { + message("poll_listener: ERROR found %d events, poll reported %d\n", nevents, ret); + } + + /* In any event, read until the pipe/serial is empty */ + + for (i = 0; i < NPOLLFDS; i++) + { + do + { +#ifdef HAVE_CONSOLE + /* Hack to work around the fact that the console driver on the + * simulator is always non-blocking. + */ + + if (i == CONSNDX) + { + if ((fds[CONSNDX].revents & POLLIN) != 0) + { + buffer[0] = getchar(); + nbytes = 1; + } + else + { + nbytes = 0; + } + } + else +#endif + { + /* The pipe works differently, it returns whatever data + * it has available without blocking. + */ + + nbytes = read(fds[i].fd, buffer, 63); + } + + if (nbytes <= 0) + { + if (nbytes == 0 || errno == EAGAIN) + { + if ((fds[i].revents & POLLIN) != 0) + { + message("poll_listener: ERROR no read data[%d]\n", i); + } + } + else if (errno != EINTR) + { + message("poll_listener: read[%d] failed: %d\n", i, errno); + } + nbytes = 0; + } + else + { + if (timeout) + { + message("poll_listener: ERROR? Poll timeout, but data read[%d]\n", i); + message(" (might just be a race condition)\n"); + } + + buffer[nbytes] = '\0'; + message("poll_listener: Read[%d] '%s' (%d bytes)\n", i, buffer, nbytes); + } + + /* Suppress error report if no read data on the next time through */ + + fds[i].revents = 0; + } + while (nbytes > 0); + } + + /* Make sure that everything is displayed */ + + msgflush(); + } + + /* Won't get here */ + + (void)close(fd); + return NULL; +} diff --git a/apps/examples/poll/poll_main.c b/apps/examples/poll/poll_main.c new file mode 100644 index 000000000..d66e7f269 --- /dev/null +++ b/apps/examples/poll/poll_main.c @@ -0,0 +1,229 @@ +/**************************************************************************** + * examples/poll/poll_main.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <poll.h> +#include <errno.h> +#include <debug.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_initialize + ****************************************************************************/ + +void user_initialize(void) +{ +} + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + char buffer[64]; + ssize_t nbytes; + pthread_t tid1; + pthread_t tid2; +#ifdef HAVE_NETPOLL + pthread_t tid3; +#endif + int count; + int fd1 = -1; + int fd2 = -1; + int ret; + int exitcode = 0; + + /* Open FIFOs */ + + message("\nuser_start: Creating FIFO %s\n", FIFO_PATH1); + ret = mkfifo(FIFO_PATH1, 0666); + if (ret < 0) + { + message("user_start: mkfifo failed: %d\n", errno); + exitcode = 1; + goto errout; + } + + message("\nuser_start: Creating FIFO %s\n", FIFO_PATH2); + ret = mkfifo(FIFO_PATH2, 0666); + if (ret < 0) + { + message("user_start: mkfifo failed: %d\n", errno); + exitcode = 2; + goto errout; + } + + /* Open the FIFOs for blocking, write */ + + fd1 = open(FIFO_PATH1, O_WRONLY); + if (fd1 < 0) + { + message("user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH1, errno); + exitcode = 3; + goto errout; + } + + fd2 = open(FIFO_PATH2, O_WRONLY); + if (fd2 < 0) + { + message("user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH2, errno); + exitcode = 4; + goto errout; + } + + /* Start the listeners */ + + message("user_start: Starting poll_listener thread\n"); + + ret = pthread_create(&tid1, NULL, poll_listener, NULL); + if (ret != 0) + { + message("user_start: Failed to create poll_listener thread: %d\n", ret); + exitcode = 5; + goto errout; + } + + message("user_start: Starting select_listener thread\n"); + + ret = pthread_create(&tid2, NULL, select_listener, NULL); + if (ret != 0) + { + message("user_start: Failed to create select_listener thread: %d\n", ret); + exitcode = 6; + goto errout; + } + +#ifdef HAVE_NETPOLL +#ifdef CONFIG_NET_TCPBACKLOG + message("user_start: Starting net_listener thread\n"); + + ret = pthread_create(&tid3, NULL, net_listener, NULL); +#else + message("user_start: Starting net_reader thread\n"); + + ret = pthread_create(&tid3, NULL, net_reader, NULL); +#endif + if (ret != 0) + { + message("user_start: Failed to create net_listener thread: %d\n", ret); + } +#endif + + /* Loop forever */ + + for (count = 0; ; count++) + { + /* Send a message to the listener... this should wake the listener + * from the poll. + */ + + sprintf(buffer, "Message %d", count); + nbytes = write(fd1, buffer, strlen(buffer)); + if (nbytes < 0) + { + message("user_start: Write to fd1 failed: %d\n", errno); + exitcode = 7; + goto errout; + } + + nbytes = write(fd2, buffer, strlen(buffer)); + if (nbytes < 0) + { + message("user_start: Write fd2 failed: %d\n", errno); + exitcode = 8; + goto errout; + } + + message("\nuser_start: Sent '%s' (%d bytes)\n", buffer, nbytes); + msgflush(); + + /* Wait awhile. This delay should be long enough that the + * listener will timeout. + */ + + sleep(WRITER_DELAY); + } + +errout: + if (fd1 >= 0) + { + close(fd1); + } + + if (fd2 >= 0) + { + close(fd2); + } + + fflush(stdout); + return exitcode; +} diff --git a/apps/examples/poll/select_listener.c b/apps/examples/poll/select_listener.c new file mode 100644 index 000000000..80039ada3 --- /dev/null +++ b/apps/examples/poll/select_listener.c @@ -0,0 +1,193 @@ +/**************************************************************************** + * examples/poll/select_listener.c + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: select_listener + ****************************************************************************/ + +void *select_listener(pthread_addr_t pvarg) +{ + fd_set rfds; + struct timeval tv; + char buffer[64]; + ssize_t nbytes; + bool timeout; + bool ready; + int fd; + int ret; + + /* Open the FIFO for non-blocking read */ + + message("select_listener: Opening %s for non-blocking read\n", FIFO_PATH2); + fd = open(FIFO_PATH2, O_RDONLY|O_NONBLOCK); + if (fd < 0) + { + message("select_listener: ERROR Failed to open FIFO %s: %d\n", + FIFO_PATH2, errno); + (void)close(fd); + return (void*)-1; + } + + /* Loop forever */ + + for (;;) + { + message("select_listener: Calling select()\n"); + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + tv.tv_sec = SELECT_LISTENER_DELAY; + tv.tv_usec = 0; + + timeout = false; + ready = false; + + ret = select(fd+1, (FAR fd_set*)&rfds, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &tv); + message("\nselect_listener: select returned: %d\n", ret); + + if (ret < 0) + { + message("select_listener: ERROR select failed: %d\n"); + } + else if (ret == 0) + { + message("select_listener: Timeout\n"); + timeout = true; + } + else + { + if (ret != 1) + { + message("select_listener: ERROR poll reported: %d\n"); + } + else + { + ready = true; + } + + if (!FD_ISSET(fd, rfds)) + { + message("select_listener: ERROR fd=%d not in fd_set\n"); + } + } + + /* In any event, read until the pipe is empty */ + + do + { + nbytes = read(fd, buffer, 63); + if (nbytes <= 0) + { + if (nbytes == 0 || errno == EAGAIN) + { + if (ready) + { + message("select_listener: ERROR no read data\n"); + } + } + else if (errno != EINTR) + { + message("select_listener: read failed: %d\n", errno); + } + nbytes = 0; + } + else + { + if (timeout) + { + message("select_listener: ERROR? Poll timeout, but data read\n"); + message(" (might just be a race condition)\n"); + } + + buffer[nbytes] = '\0'; + message("select_listener: Read '%s' (%d bytes)\n", buffer, nbytes); + } + + timeout = false; + ready = false; + } + while (nbytes > 0); + + /* Make sure that everything is displayed */ + + msgflush(); + } + + /* Won't get here */ + + (void)close(fd); + return NULL; +} |