summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapps/ChangeLog.txt10
-rw-r--r--apps/examples/Makefile6
-rw-r--r--apps/examples/README.txt22
-rw-r--r--apps/examples/telnetd/Makefile105
-rw-r--r--apps/examples/telnetd/README.txt8
-rw-r--r--apps/examples/telnetd/shell.c251
-rw-r--r--apps/examples/telnetd/shell.h103
-rw-r--r--apps/include/netutils/telnetd.h118
-rw-r--r--apps/netutils/README.txt7
-rw-r--r--apps/netutils/telnetd/Makefile6
-rw-r--r--apps/netutils/telnetd/README.txt9
-rw-r--r--apps/netutils/telnetd/shell.c139
-rw-r--r--apps/netutils/telnetd/shell.h97
-rw-r--r--apps/netutils/telnetd/telnetd.c459
-rw-r--r--apps/netutils/telnetd/telnetd.h115
-rw-r--r--apps/netutils/telnetd/telnetd_daemon.c349
-rw-r--r--apps/netutils/telnetd/telnetd_driver.c735
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/include/net/psock.h312
-rw-r--r--nuttx/net/net_close.c12
-rw-r--r--nuttx/net/net_internal.h12
-rw-r--r--nuttx/net/net_poll.c4
-rw-r--r--nuttx/net/net_sockets.c8
-rw-r--r--nuttx/net/recv.c4
-rw-r--r--nuttx/net/recvfrom.c83
-rw-r--r--nuttx/net/send.c80
-rw-r--r--nuttx/net/sendto.c99
27 files changed, 2373 insertions, 782 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 77b92d12c..1179e2614 100755
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -164,3 +164,13 @@
a USB serial console, then NSH needs to wait until the USB console is
connected and available.
* apps/examples/composite: Add a test of the USB composite device.
+ * apps/examples/telnetd: Move the tiny uIP shell example from
+ netutils/telnetd to examples/telnetd. Enhanced the telnetd daemon so that
+ it supports telnetd via a TTY device driver: A new TTY device driver is
+ created when each new telnet connection is created. The shell thread
+ is started with stdin, stdout, and stderror mapped to the TTY device.
+ * netutils/telnetd: The old uIP telnet demo is gone. In its place is a new
+ telnet infrastructure. The new telnet daemon creates sessions that are
+ "wrapped" as character devices and mapped to stdin, stdout, and stderr.
+ Now the telnet session can be inherited by spawned tasks.
+ * examples/telnetd: Add a test for the nte telnet daemon.
diff --git a/apps/examples/Makefile b/apps/examples/Makefile
index c2e5fe3de..3847c2b12 100644
--- a/apps/examples/Makefile
+++ b/apps/examples/Makefile
@@ -40,8 +40,8 @@
SUBDIRS = adc buttons can composite dhcpd ftpc hello helloxx hidkbd igmp \
lcdrw mm mount nettest nsh null nx nxffs nxflat nxhello nximage \
nxlines nxtext ostest pashello pipe poll pwm rgmp romfs sendmail \
- serloop thttpd tiff touchscreen udp uip usbserial usbstorage usbterm \
- wget wlan
+ serloop telnetd thttpd tiff touchscreen udp uip usbserial \
+ usbstorage usbterm wget wlan
# Sub-directories that might need context setup. Directories may need
# context setup for a variety of reasons, but the most common is because
@@ -56,7 +56,7 @@ SUBDIRS = adc buttons can composite dhcpd ftpc hello helloxx hidkbd igmp \
CNTXTDIRS = pwm
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
-CNTXTDIRS += adc can composite dhcpd nettest
+CNTXTDIRS += adc can composite dhcpd nettest telnetd
endif
ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y)
diff --git a/apps/examples/README.txt b/apps/examples/README.txt
index 3dc8bdfb2..b14d19b84 100644
--- a/apps/examples/README.txt
+++ b/apps/examples/README.txt
@@ -894,6 +894,28 @@ examples/serloop
Use C buffered I/O (getchar/putchar) vs. raw console I/O
(read/read).
+examples/telnetd
+^^^^^^^^^^^^^^^^
+
+ This directory contains a functional port of the tiny uIP shell. In
+ the NuttX environment, the NuttShell (at apps/nshlib) supercedes this
+ tiny shell and also supports telnetd.
+
+ CONFIG_EXAMPLES_TELNETD_DAEMONPRIO - Priority of the Telnet daemon.
+ Default: SCHED_PRIORITY_DEFAULT
+ CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the
+ Telnet daemon. Default: 2048
+ CONFIG_EXAMPLES_TELNETD_CLIENTPRIO- Priority of the Telnet client.
+ Default: SCHED_PRIORITY_DEFAULT
+ CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the
+ Telnet client. Default: 2048
+ CONFIG_EXAMPLE_TELNETD_NOMAC - If the hardware has no MAC address of its
+ own, define this =y to provide a bogus address for testing.
+ CONFIG_EXAMPLE_TELNETD_IPADDR - The target IP address. Default 10.0.0.2
+ CONFIG_EXAMPLE_TELNETD_DRIPADDR - The default router address. Default
+ 10.0.0.1
+ CONFIG_EXAMPLE_TELNETD_NETMASK - The network mask. Default: 255.255.255.0
+
examples/thttpd
^^^^^^^^^^^^^^^
diff --git a/apps/examples/telnetd/Makefile b/apps/examples/telnetd/Makefile
new file mode 100644
index 000000000..dcb6615cc
--- /dev/null
+++ b/apps/examples/telnetd/Makefile
@@ -0,0 +1,105 @@
+############################################################################
+# apps/examples/telnetd/Makefile
+#
+# Copyright (C) 2012 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
+
+# Hello, World! Example
+
+ASRCS =
+CSRCS = shell.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(WINTOOL),y)
+ BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}"
+else
+ BIN = "$(APPDIR)/libapps$(LIBEXT)"
+endif
+
+ROOTDEPPATH = --dep-path .
+
+# Buttons built-in application info
+
+APPNAME = buttons
+PRIORITY = SCHED_PRIORITY_DEFAULT
+STACKSIZE = 2048
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: context clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $(BIN), $${obj}); \
+ done ; )
+ @touch .built
+
+.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+ $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
+ @touch $@
+endif
+
+context: .context
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ @rm -f *.o *~ .*.swp .built
+ $(call CLEAN)
+
+distclean: clean
+ @rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/apps/examples/telnetd/README.txt b/apps/examples/telnetd/README.txt
new file mode 100644
index 000000000..ebc9684ca
--- /dev/null
+++ b/apps/examples/telnetd/README.txt
@@ -0,0 +1,8 @@
+README.txt
+^^^^^^^^^^
+
+This directory contains a functional port of the tiny uIP shell. In the
+NuttX environment, the NuttShell (at apps/nshlib) supercedes this tiny
+shell and also supports telnetd.
+
+This example is retained here for reference purposes only.
diff --git a/apps/examples/telnetd/shell.c b/apps/examples/telnetd/shell.c
new file mode 100644
index 000000000..69f348615
--- /dev/null
+++ b/apps/examples/telnetd/shell.c
@@ -0,0 +1,251 @@
+/****************************************************************************
+ * examples/telnetd/shell.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * This is a leverage of similar logic from uIP:
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * 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 of the Institute 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 INSTITUTE 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 INSTITUTE 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <apps/netutils/telnetd.h>
+#include <apps/netutils/uiplib.h>
+#include "shell.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ptentry_s
+{
+ FAR const char *commandstr;
+ void (*pfunc)(int argc, char **argv);
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void shell_help(int argc, char **argv);
+static void shell_quit(int argc, char **argv);
+static void shell_unknown(int argc, char **argv);
+static void shell_parse(FAR char *line, int len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct ptentry_s g_parsetab[] =
+{
+ {"help", shell_help},
+ {"exit", shell_quit},
+ {"?", shell_help},
+ {NULL, shell_unknown}
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: shell_help
+ ****************************************************************************/
+
+static void shell_help(int argc, char **argv)
+{
+ printf("Available commands:");
+ printf(" help, ? - show help");
+ printf(" exit - exit shell");
+}
+
+/****************************************************************************
+ * Name: shell_help
+ ****************************************************************************/
+
+static void shell_unknown(int argc, char **argv)
+{
+ if (argv[0])
+ {
+ printf("Unknown command: %s\n", argv[0]);
+ }
+}
+
+/****************************************************************************
+ * Name: shell_quit
+ ****************************************************************************/
+
+static void shell_quit(int argc, char **argv)
+{
+ printf("Bye!\n");
+ exit(0);
+}
+
+/****************************************************************************
+ * Name: shell_parse
+ ****************************************************************************/
+
+static void shell_parse(FAR char *line, int len)
+{
+ struct ptentry_s *entry;
+ FAR char *cmd;
+ FAR char *saveptr;
+
+ /* Get the command from the beginning the line */
+
+ cmd = strtok_r(line, " \t\n\r\f\v", &saveptr);
+ if (cmd)
+ {
+ /* Now find the matching command in the command table */
+
+ for (entry = g_parsetab; entry->commandstr != NULL; entry++)
+ {
+ if (strncmp(entry->commandstr, cmd, strlen(entry->commandstr)) == 0)
+ {
+ break;
+ }
+ }
+
+ entry->pfunc(1, &cmd);
+ }
+}
+
+/****************************************************************************
+ * Name: shell_session
+ ****************************************************************************/
+
+int shell_session(int argc, char *argv[])
+{
+ char line[128];
+
+ printf("uIP command shell -- NuttX style");
+ printf("Type '?' and return for help");
+
+ for(;;)
+ {
+ printf(SHELL_PROMPT);
+
+ if (fgets(line, 128, stdin) == NULL)
+ {
+ break;
+ }
+
+ shell_parse(line, 128);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: shell_netinit
+ ****************************************************************************/
+
+static void shell_netinit(void)
+{
+ struct in_addr addr;
+#ifdef CONFIG_EXAMPLE_TELNETD_NOMAC
+ uint8_t mac[IFHWADDRLEN];
+#endif
+
+/* Many embedded network interfaces must have a software assigned MAC */
+
+#ifdef CONFIG_EXAMPLE_TELNETD_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_TELNETD_IPADDR);
+ uip_sethostaddr("eth0", &addr);
+
+ /* Set up the default router address */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_TELNETD_DRIPADDR);
+ uip_setdraddr("eth0", &addr);
+
+ /* Setup the subnet mask */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_TELNETD_NETMASK);
+ uip_setnetmask("eth0", &addr);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int MAIN_NAME(int argc, char *argv[])
+{
+ struct telnetd_config_s config;
+ int ret;
+
+ /* Configure the network */
+
+ printf(MAIN_STRING "Initializing the network\n");
+ shell_netinit();
+
+ /* Configure the telnet daemon */
+
+ config.d_port = HTONS(23);
+ config.d_priority = CONFIG_EXAMPLES_TELNETD_DAEMONPRIO;
+ config.d_stacksize = CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE;
+ config.t_priority = CONFIG_EXAMPLES_TELNETD_CLIENTPRIO;
+ config.t_stacksize = CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE;
+ config.t_entry = shell_session;
+
+ /* Start the telnet daemon */
+
+ printf(MAIN_STRING "Starting the Telnet daemon\n");
+ ret = telnetd_start(&config);
+ if (ret < 0)
+ {
+ printf("Failed to tart the Telnet daemon\n");
+ }
+
+ printf(MAIN_STRING "Exiting\n");
+ return 0;
+}
diff --git a/apps/examples/telnetd/shell.h b/apps/examples/telnetd/shell.h
new file mode 100644
index 000000000..96aab1319
--- /dev/null
+++ b/apps/examples/telnetd/shell.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * apps/examples/telnetd/shell.h
+ * Interface for the Contiki shell.
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __APPS_EXAMPLES_TELNETD_SHELL_H
+#define __APPS_EXAMPLES_TELNETD_SHELL_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+/* CONFIG_EXAMPLES_TELNETD_DAEMONPRIO - Priority of the Telnet daemon.
+ * Default: SCHED_PRIORITY_DEFAULT
+ * CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the
+ * Telnet daemon. Default: 2048
+ * CONFIG_EXAMPLES_TELNETD_CLIENTPRIO- Priority of the Telnet client.
+ * Default: SCHED_PRIORITY_DEFAULT
+ * CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the
+ * Telnet client. Default: 2048
+ * CONFIG_EXAMPLE_TELNETD_NOMAC - If the hardware has no MAC address of its
+ * own, define this =y to provide a bogus address for testing.
+ * CONFIG_EXAMPLE_TELNETD_IPADDR - The target IP address. Default 10.0.0.2
+ * CONFIG_EXAMPLE_TELNETD_DRIPADDR - The default router address. Default
+ * 10.0.0.1
+ * CONFIG_EXAMPLE_TELNETD_NETMASK - The network mask. Default: 255.255.255.0
+ */
+
+#ifndef CONFIG_EXAMPLES_TELNETD_DAEMONPRIO
+# define CONFIG_EXAMPLES_TELNETD_DAEMONPRIO SCHED_PRIORITY_DEFAULT
+#endif
+
+#ifndef CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE
+# define CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE 2048
+#endif
+
+#ifndef CONFIG_EXAMPLES_TELNETD_CLIENTPRIO
+# define CONFIG_EXAMPLES_TELNETD_CLIENTPRIO SCHED_PRIORITY_DEFAULT
+#endif
+
+#ifndef CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE
+# define CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE 2048
+#endif
+
+#ifndef CONFIG_EXAMPLE_TELNETD_IPADDR
+# define CONFIG_EXAMPLE_TELNETD_IPADDR 0x0a000002
+#endif
+#ifndef CONFIG_EXAMPLE_TELNETD_DRIPADDR
+# define CONFIG_EXAMPLE_TELNETD_DRIPADDR 0x0a000002
+#endif
+#ifndef CONFIG_EXAMPLE_TELNETD_NETMASK
+# define CONFIG_EXAMPLE_TELNETD_NETMASK 0xffffff00
+#endif
+
+/* Is this being built as an NSH built-in application? */
+
+#ifdef CONFIG_NSH_BUILTIN_APPS
+# define MAIN_NAME shell_main
+# define MAIN_STRING "shell_main: "
+#else
+# define MAIN_NAME user_start
+# define MAIN_STRING "user_start: "
+#endif
+
+
+/* Other definitions ********************************************************/
+
+#define SHELL_PROMPT "uIP 1.0> "
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* __APPS_EXAMPLES_TELNETD_SHELL_H */
diff --git a/apps/include/netutils/telnetd.h b/apps/include/netutils/telnetd.h
index 9d3d6feaf..37e7dfd4f 100644
--- a/apps/include/netutils/telnetd.h
+++ b/apps/include/netutils/telnetd.h
@@ -1,14 +1,8 @@
/****************************************************************************
* include/apps/netutils/telnetd.h
*
- * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * This is a leverage of similar logic from uIP:
- *
- * Author: Adam Dunkels <adam@sics.se>
- * Copyright (c) 2003, Adam Dunkels.
- * All rights reserved.
+ * Copyright (C) 2007, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -17,35 +11,83 @@
* 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 of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt 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 INSTITUTE 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 INSTITUTE 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.
+ * 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 __APPS_NETUTILS_TELNETD_H
-#define __APPS_NETUTILS_TELNETD_H
+#ifndef __APPS_INCLUDE_NETUTILS_TELNETD_H
+#define __APPS_INCLUDE_NETUTILS_TELNETD_H
/****************************************************************************
* Included Files
****************************************************************************/
+#include <nuttx/config.h>
+
/****************************************************************************
- * Included Files
+ * Pre-processor Definitions
****************************************************************************/
+/* CONFIG_TELNETD_CONSOLE - Use the first telnet session as the default
+ * console.
+ * CONFIG_TELNETD_NPOLLWAITERS - If the poll method is enabled, then this
+ * value will defined the maximum number of threads that can be waiting
+ * for events. Default: 1
+ * CONFIG_TELNETD_DUMPBUFFER - dumping of all input/output buffers.
+ */
+
+#ifndef CONFIG_TELNETD_NPOLLWAITERS
+# define CONFIG_TELNETD_NPOLLWAITERS 1
+#endif
+
+/* Configurable settings */
+
+#ifndef CONFIG_TELNETD_IOBUFFER_SIZE
+# define CONFIG_TELNETD_IOBUFFER_SIZE 512
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+ /* An instance of the struct telnetd_config_s structure must be passed to
+ * telnetd_start in order to configure the new telnet daemon.
+ */
+
+struct telnetd_config_s
+{
+ /* These fields describe the telnet daemon */
+
+ int d_port; /* The port to listen on (in network byte order) */
+ int d_priority; /* The execution priority of the telnet daemon task */
+ int d_stacksize; /* The stack size needed by the telnet daemon task */
+
+ /* These fields describe the priority of each thread created by the telnet
+ * daemon.
+ */
+
+ int t_priority; /* The execution priority of the spawned task, */
+ int t_stacksize; /* The stack size needed by the spawned task */
+ main_t t_entry; /* The entrypoint of the task to spawn when a new
+ * connection is accepted. */
+};
/****************************************************************************
* Public Function Prototypes
@@ -58,13 +100,29 @@ extern "C" {
#define EXTERN extern
#endif
-/* Start the telnet server -- does not return unless an error occurs */
+/****************************************************************************
+ * Name: telnetd_start
+ *
+ * Description:
+ * Start the telnet daemon.
+ *
+ * Parameters:
+ * config A pointer to a configuration structure that characterizes the
+ * telnet daemon. This configuration structure may be defined
+ * on the caller's stack because it is not retained by the
+ * daemon.
+ *
+ * Return:
+ * The process ID (pid) of the new telnet daemon is returned on
+ * success; A negated errno is returned if the daemon was not successfully
+ * started.
+ *
+ ****************************************************************************/
-EXTERN void telnetd_init(void);
+EXTERN int telnetd_start(FAR struct telnetd_config_s *config);
#undef EXTERN
#ifdef __cplusplus
}
#endif
-
-#endif /* __APPS_NETUTILS_TELNETD_H */
+#endif /* __APPS_INCLUDE_NETUTILS_TELNETD_H */
diff --git a/apps/netutils/README.txt b/apps/netutils/README.txt
index 2059b569e..ea9dbd5c3 100644
--- a/apps/netutils/README.txt
+++ b/apps/netutils/README.txt
@@ -9,7 +9,6 @@ include:
dhcpc - Dynamic Host Configuration Protocol (DHCP) client
resolv - uIP DNS resolver
smtp - Simple Mail Transfer Protocol (SMTP) client
- telnetd - TELNET server
webclient - HTTP web client
webserver - HTTP web server
@@ -21,6 +20,12 @@ highly influenced by uIP) include:
dhcpd - Dynamic Host Configuration Protocol (DHCP) server
tftpc - TFTP client
+ telnetd - TELNET server. This is the Telnet logic adapted from
+ uIP and generalized for use as the front end to any
+ shell. The telnet daemon creates sessions that are
+ "wrapped" as character devices and mapped to stdin,
+ stdout, and stderr. Now the telnet session can be
+ inherited by spawned tasks.
ftpc - FTP client
thttpd - This is a port of Jef Poskanzer's THTTPD HTPPD server.
See http://acme.com/software/thttpd/.
diff --git a/apps/netutils/telnetd/Makefile b/apps/netutils/telnetd/Makefile
index cba7f0c70..fac6df571 100644
--- a/apps/netutils/telnetd/Makefile
+++ b/apps/netutils/telnetd/Makefile
@@ -1,8 +1,8 @@
############################################################################
# apps/netutils/telnetd/Makefile
#
-# Copyright (C) 2011 Gregory Nutt. All rights reserved.
-# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -43,7 +43,7 @@ ASRCS =
CSRCS =
ifeq ($(CONFIG_NET_TCP),y)
-CSRCS += telnetd.c shell.c
+CSRCS += telnetd_daemon.c telnetd_driver.c
endif
AOBJS = $(ASRCS:.S=$(OBJEXT))
diff --git a/apps/netutils/telnetd/README.txt b/apps/netutils/telnetd/README.txt
index 24fcba7d5..367cef0a2 100644
--- a/apps/netutils/telnetd/README.txt
+++ b/apps/netutils/telnetd/README.txt
@@ -1,7 +1,4 @@
-This directory is here for historical reasons. Nothing contained in this
-directory is currently used by NuttX. This directly contains a functional
-port of the tiny uIP shell. In the NuttX environment, the NuttShell (at
-apps/nshlib) supercedes this tiny shell and also supports telnetd.
-
-This example is retained here for reference purposes only.
+README.txt
+^^^^^^^^^^
+This directly contains a generic Telnet daemon.
diff --git a/apps/netutils/telnetd/shell.c b/apps/netutils/telnetd/shell.c
deleted file mode 100644
index 93fd11601..000000000
--- a/apps/netutils/telnetd/shell.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/****************************************************************************
- * netutils/telnetd/telnetd.c
- *
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * This is a leverage of similar logic from uIP:
- *
- * Author: Adam Dunkels <adam@sics.se>
- * Copyright (c) 2003, Adam Dunkels.
- * All rights reserved.
- *
- * 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 of the Institute 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 INSTITUTE 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 INSTITUTE 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 <string.h>
-#include "shell.h"
-
-/****************************************************************************
- * Definitions
- ****************************************************************************/
-
-#define SHELL_PROMPT "uIP 1.0> "
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-struct ptentry_s
-{
- char *commandstr;
- void (* pfunc)(void *handle, char *str);
-};
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-static void parse(void *handle, register char *str, struct ptentry_s *t);
-static void help(void *handle, char *str);
-static void unknown(void *handle, char *str);
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-static struct ptentry_s g_parsetab[] =
-{
- {"stats", help},
- {"conn", help},
- {"help", help},
- {"exit", shell_quit},
- {"?", help},
- {NULL, unknown}
-};
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-static void parse(void *handle, char *str, struct ptentry_s *t)
-{
- struct ptentry_s *p;
-
- for (p = t; p->commandstr != NULL; ++p)
- {
- if (strncmp(p->commandstr, str, strlen(p->commandstr)) == 0)
- {
- break;
- }
- }
-
- p->pfunc(handle, str);
-}
-
-static void help(void *handle, char *str)
-{
- shell_output(handle, "Available commands:");
- shell_output(handle, "stats - show network statistics");
- shell_output(handle, "conn - show TCP connections");
- shell_output(handle, "help, ? - show help");
- shell_output(handle, "exit - exit shell");
-}
-
-static void unknown(void *handle, char *str)
-{
- if (strlen(str) > 0)
- {
- shell_output(handle, "Unknown command: ", str);
- }
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-void shell_init(void *handle)
-{
-}
-
-void shell_start(void *handle)
-{
- shell_output(handle, "uIP command shell");
- shell_output(handle, "Type '?' and return for help");
- shell_prompt(handle, SHELL_PROMPT);
-}
-
-void shell_input(void *handle, char *cmd)
-{
- parse(handle, cmd, g_parsetab);
- shell_prompt(handle, SHELL_PROMPT);
-}
diff --git a/apps/netutils/telnetd/shell.h b/apps/netutils/telnetd/shell.h
deleted file mode 100644
index 32325fe17..000000000
--- a/apps/netutils/telnetd/shell.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
- * netutils/telnetd/shell.h
- * Interface for the Contiki shell.
- *
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * Based on uIP which also has a BSD style license:
- *
- * Author: Adam Dunkels <adam@dunkels.com>
- * Copyright (c) 2003, Adam Dunkels.
- * All rights reserved.
- *
- * 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. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- ****************************************************************************/
-
-/* Some of the functions declared in this file must be implemented as
- * a shell back-end in the architecture specific files of a Contiki
- * port.
- */
-
-#ifndef __SHELL_H__
-#define __SHELL_H__
-
-/* Initialize the shell.
- *
- * Called when the shell front-end process starts. This function may
- * be used to start listening for signals.
- */
-
-void shell_init(void *handle);
-
-/* Start the shell back-end.
- *
- * Called by the front-end when a new shell is started.
- */
-
-void shell_start(void *handle);
-
-/* Process a shell command.
- *
- * This function will be called by the shell GUI / telnet server whan
- * a command has been entered that should be processed by the shell
- * back-end.
- *
- * command The command to be processed.
- */
-
-void shell_input(void *handle, char *command);
-
-/* Quit the shell. */
-
-void shell_quit(void *handle, char *);
-
-/* Print a string to the shell window.
- *
- * This function is implemented by the shell GUI / telnet server and
- * can be called by the shell back-end to output a string in the
- * shell window. The string is automatically appended with a linebreak.
- */
-
-void shell_output(void *handle, const char *fmt, ...);
-
-/* Print a prompt to the shell window.
- *
- * This function can be used by the shell back-end to print out a
- * prompt to the shell window.
- *
- */
-
-void shell_prompt(void *handle, char *prompt);
-
-#endif /* __SHELL_H__ */
diff --git a/apps/netutils/telnetd/telnetd.c b/apps/netutils/telnetd/telnetd.c
deleted file mode 100644
index ccadd60dd..000000000
--- a/apps/netutils/telnetd/telnetd.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/****************************************************************************
- * netutils/telnetd/telnetd.c
- *
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * This is a leverage of similar logic from uIP:
- *
- * Author: Adam Dunkels <adam@sics.se>
- * Copyright (c) 2003, Adam Dunkels.
- * All rights reserved.
- *
- * 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 of the Institute 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 INSTITUTE 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 INSTITUTE 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/socket.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <pthread.h>
-#include <debug.h>
-
-#include <apps/netutils/telnetd.h>
-#include <apps/netutils/uiplib.h>
-
-#include "shell.h"
-
-/****************************************************************************
- * Definitions
- ****************************************************************************/
-
-#define ISO_nl 0x0a
-#define ISO_cr 0x0d
-
-#define STATE_NORMAL 0
-#define STATE_IAC 1
-#define STATE_WILL 2
-#define STATE_WONT 3
-#define STATE_DO 4
-#define STATE_DONT 5
-#define STATE_CLOSE 6
-
-#define TELNET_IAC 255
-#define TELNET_WILL 251
-#define TELNET_WONT 252
-#define TELNET_DO 253
-#define TELNET_DONT 254
-
-/* Configurable settings */
-
-#ifndef CONFIG_NETUTILS_IOBUFFER_SIZE
-# define CONFIG_NETUTILS_IOBUFFER_SIZE 512
-#endif
-
-#ifndef CONFIG_NETUTILS_CMD_SIZE
-# define CONFIG_NETUTILS_CMD_SIZE 40
-#endif
-
-/* As threads are created to handle each request, a stack must be allocated
- * for the thread. Use a default if the user provided no stacksize.
- */
-
-#ifndef CONFIG_NETUTILS_TELNETDSTACKSIZE
-# define CONFIG_NETUTILS_TELNETDSTACKSIZE 4096
-#endif
-
-/* Enabled dumping of all input/output buffers */
-
-#undef CONFIG_NETUTILS_TELNETD_DUMPBUFFER
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-struct telnetd_s
-{
- int tn_sockfd;
- char tn_iobuffer[CONFIG_NETUTILS_IOBUFFER_SIZE];
- char tn_cmd[CONFIG_NETUTILS_CMD_SIZE];
- uint8_t tn_bufndx;
- uint8_t tn_state;
-};
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: telnetd_dumpbuffer
- *
- * Description:
- * Dump a buffer of data (debug only)
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NETUTILS_TELNETD_DUMPBUFFER
-static inline void telnetd_dumpbuffer(FAR const char *msg, FAR const char *buffer, unsigned int nbytes)
-{
- /* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_NET have to be
- * defined or the following does nothing.
- */
-
- nvdbgdumpbuffer(msg, (FAR const uint8_t*)buffer, nbytes);
-}
-#else
-# define telnetd_dumpbuffer(msg,buffer,nbytes)
-#endif
-
-/****************************************************************************
- * Name: telnetd_putchar
- *
- * Description:
- * Add another parsed character to the TELNET command string
- *
- ****************************************************************************/
-
-static void telnetd_putchar(struct telnetd_s *pstate, uint8_t ch)
-{
- /* Ignore carriage returns */
-
- if (ch == ISO_cr)
- {
- return;
- }
-
- /* Add all other characters to the cmd buffer */
-
- pstate->tn_cmd[pstate->tn_bufndx] = ch;
-
- /* If a newline was added or if the buffer is full, then process it now */
-
- if (ch == ISO_nl || pstate->tn_bufndx == (CONFIG_NETUTILS_CMD_SIZE - 1))
- {
- if (pstate->tn_bufndx > 0)
- {
- pstate->tn_cmd[pstate->tn_bufndx] = '\0';
- }
-
- telnetd_dumpbuffer("TELNET CMD", pstate->tn_cmd, strlen(pstate->tn_cmd));
- shell_input(pstate, pstate->tn_cmd);
- pstate->tn_bufndx = 0;
- }
- else
- {
- pstate->tn_bufndx++;
- vdbg("Add '%c', bufndx=%d\n", ch, pstate->tn_bufndx);
- }
-}
-
-/****************************************************************************
- * Name: telnetd_sendopt
- *
- * Description:
- *
- ****************************************************************************/
-
-static void telnetd_sendopt(struct telnetd_s *pstate, uint8_t option, uint8_t value)
-{
- uint8_t optbuf[4];
- optbuf[0] = TELNET_IAC;
- optbuf[1] = option;
- optbuf[2] = value;
- optbuf[3] = 0;
-
- telnetd_dumpbuffer("Send optbuf", optbuf, 4);
- if (send(pstate->tn_sockfd, optbuf, 4, 0) < 0)
- {
- dbg("[%d] Failed to send TELNET_IAC\n", pstate->tn_sockfd);
- }
-}
-
-/****************************************************************************
- * Name: telnetd_receive
- *
- * Description:
- * Process a received TELENET buffer
- *
- ****************************************************************************/
-
-static int telnetd_receive(struct telnetd_s *pstate, size_t len)
-{
- char *ptr = pstate->tn_iobuffer;
- uint8_t ch;
-
- while (len > 0)
- {
- ch = *ptr++;
- len--;
-
- vdbg("ch=%02x state=%d\n", ch, pstate->tn_state);
- switch (pstate->tn_state)
- {
- case STATE_IAC:
- if (ch == TELNET_IAC)
- {
- telnetd_putchar(pstate, ch);
- pstate->tn_state = STATE_NORMAL;
- }
- else
- {
- switch (ch)
- {
- case TELNET_WILL:
- pstate->tn_state = STATE_WILL;
- break;
-
- case TELNET_WONT:
- pstate->tn_state = STATE_WONT;
- break;
-
- case TELNET_DO:
- pstate->tn_state = STATE_DO;
- break;
-
- case TELNET_DONT:
- pstate->tn_state = STATE_DONT;
- break;
-
- default:
- pstate->tn_state = STATE_NORMAL;
- break;
- }
- }
- break;
-
- case STATE_WILL:
- /* Reply with a DONT */
-
- telnetd_sendopt(pstate, TELNET_DONT, ch);
- pstate->tn_state = STATE_NORMAL;
- break;
-
- case STATE_WONT:
- /* Reply with a DONT */
-
- telnetd_sendopt(pstate, TELNET_DONT, ch);
- pstate->tn_state = STATE_NORMAL;
- break;
-
- case STATE_DO:
- /* Reply with a WONT */
-
- telnetd_sendopt(pstate, TELNET_WONT, ch);
- pstate->tn_state = STATE_NORMAL;
- break;
-
- case STATE_DONT:
- /* Reply with a WONT */
-
- telnetd_sendopt(pstate, TELNET_WONT, ch);
- pstate->tn_state = STATE_NORMAL;
- break;
-
- case STATE_NORMAL:
- if (ch == TELNET_IAC)
- {
- pstate->tn_state = STATE_IAC;
- }
- else
- {
- telnetd_putchar(pstate, ch);
- }
- break;
- }
- }
- return OK;
-}
-
-/****************************************************************************
- * Name: telnetd_handler
- *
- * Description:
- * Each time a new connection to port 23 is made, a new thread is created
- * that begins at this entry point. There should be exactly one argument
- * and it should be the socket descriptor (+1).
- *
- ****************************************************************************/
-
-static void *telnetd_handler(void *arg)
-{
- struct telnetd_s *pstate = (struct telnetd_s *)malloc(sizeof(struct telnetd_s));
- int sockfd = (int)arg;
- int ret = ERROR;
-
- dbg("[%d] Started\n", sockfd);
-
- /* Verify that the state structure was successfully allocated */
-
- if (pstate)
- {
- /* Initialize the thread state structure */
-
- memset(pstate, 0, sizeof(struct telnetd_s));
- pstate->tn_sockfd = sockfd;
- pstate->tn_state = STATE_NORMAL;
-
- /* Start up the shell */
-
- shell_init(pstate);
- shell_start(pstate);
-
- /* Loop processing each TELNET command */
- do
- {
- /* Read a buffer of data from the TELNET client */
-
- ret = recv(pstate->tn_sockfd, pstate->tn_iobuffer, CONFIG_NETUTILS_IOBUFFER_SIZE, 0);
- if (ret > 0)
- {
-
- /* Process the received TELNET data */
-
- telnetd_dumpbuffer("Received buffer", pstate->tn_iobuffer, ret);
- ret = telnetd_receive(pstate, ret);
- }
- }
- while (ret >= 0 && pstate->tn_state != STATE_CLOSE);
- dbg("[%d] ret=%d tn_state=%d\n", sockfd, ret, pstate->tn_state);
-
- /* End of command processing -- Clean up and exit */
-
- free(pstate);
- }
-
- /* Exit the task */
-
- dbg("[%d] Exitting\n", sockfd);
- close(sockfd);
- return NULL;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: telnetd_init
- *
- * Description:
- * This is the main processing thread for telnetd. It never returns
- * unless an error occurs
- *
- ****************************************************************************/
-
-void telnetd_init(void)
-{
- /* Execute telnetd_handler on each connection to port 23 */
-
- uip_server(HTONS(23), telnetd_handler, CONFIG_NETUTILS_TELNETDSTACKSIZE);
-}
-
-/****************************************************************************
- * Name: shell_prompt
- *
- * Description:
- * Print a prompt to the shell window.
- *
- * This function can be used by the shell back-end to print out a prompt
- * to the shell window.
- *
- ****************************************************************************/
-
-void shell_prompt(void *handle, char *str)
-{
- struct telnetd_s *pstate = (struct telnetd_s *)handle;
- int len = strlen(str);
-
- strncpy(pstate->tn_iobuffer, str, len);
- telnetd_dumpbuffer("Shell prompt", pstate->tn_iobuffer, len);
- if (send(pstate->tn_sockfd, pstate->tn_iobuffer, len, 0) < 0)
- {
- dbg("[%d] Failed to send prompt\n", pstate->tn_sockfd);
- }
-}
-
-/****************************************************************************
- * Name: shell_output
- *
- * Description:
- * Print a string to the shell window.
- *
- * This function is implemented by the shell GUI / telnet server and
- * can be called by the shell back-end to output a string in the
- * shell window. The string is automatically appended with a linebreak.
- *
- ****************************************************************************/
-
-void shell_output(void *handle, const char *fmt, ...)
-{
- struct telnetd_s *pstate = (struct telnetd_s *)handle;
- unsigned len;
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(pstate->tn_iobuffer, CONFIG_NETUTILS_IOBUFFER_SIZE, fmt, ap);
- va_end(ap);
-
- len = strlen(pstate->tn_iobuffer);
- if (len < CONFIG_NETUTILS_IOBUFFER_SIZE - 2)
- {
- pstate->tn_iobuffer[len] = ISO_cr;
- pstate->tn_iobuffer[len+1] = ISO_nl;
- pstate->tn_iobuffer[len+2] = '\0';
- }
-
- telnetd_dumpbuffer("Shell output", pstate->tn_iobuffer, len+2);
- if (send(pstate->tn_sockfd, pstate->tn_iobuffer, len+2, 0) < 0)
- {
- dbg("[%d] Failed to send response\n", pstate->tn_sockfd);
- }
-}
-
-/****************************************************************************
- * Name: shell_quit
- *
- * Description:
- * Quit the shell
- *
- ****************************************************************************/
-
-void shell_quit(void *handle, char *str)
-{
- struct telnetd_s *pstate = (struct telnetd_s *)handle;
- pstate->tn_state = STATE_CLOSE;
-}
-
diff --git a/apps/netutils/telnetd/telnetd.h b/apps/netutils/telnetd/telnetd.h
new file mode 100644
index 000000000..957c6c550
--- /dev/null
+++ b/apps/netutils/telnetd/telnetd.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+ * apps/netutils/telnetd/telnetd.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 Gregory Nutt 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 __APPS_NETUTILS_TELNETD_TELNETD_H
+#define __APPS_NETUTILS_TELNETD_TELNETD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This structure represents the overall state of one telnet daemon instance
+ * (Yes, multiple telnet daemons are supported).
+ */
+
+struct telnetd_s
+{
+ int port; /* The port to listen on (in network byte order) */
+ int priority; /* The execution priority of the spawned task, */
+ int stacksize; /* The stack size needed by the spawned task */
+ main_t entry; /* The entrypoint of the task to spawn when a new
+ * connection is accepted. */
+};
+
+/* This structure is used to passed information to telnet daemon when it
+ * started. It contains global information visable to all telnet daemons.
+ */
+
+struct telnetd_common_s
+{
+ uint8_t ndaemons; /* The total number of daemons running */
+ sem_t startsem; /* Enforces one-at-a-time startup */
+ sem_t exclsem; /* Enforces exclusive access to 'minor' */
+ FAR struct telnetd_s *daemon; /* Describes the new daemon */
+ int minor; /* The next minor number to use */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* This structure is used to passed information to telnet daemon when it
+ * started. It contains global information visable to all telnet daemons.
+ */
+
+extern struct telnetd_common_s g_telnetdcommon;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: telnetd_driver
+ *
+ * Description:
+ * Create a character driver to "wrap" the telnet session. This function
+ * will select and return a unique path for the new telnet device.
+ *
+ * Parameters:
+ * sd - The socket descriptor that represents the new telnet connection.
+ * daemon - A pointer to the structure representing the overall state of
+ * this instance of the telnet daemon.
+ *
+ * Return:
+ * An allocated string represent the full path to the created driver. The
+ * receiver of the string must de-allocate this memory when it is no longer
+ * needed. NULL is returned on a failure.
+ *
+ ****************************************************************************/
+
+FAR char *telnetd_driver(int sd, FAR struct telnetd_s *daemon);
+
+#endif /* __APPS_NETUTILS_TELNETD_TELNETD_H */
+
diff --git a/apps/netutils/telnetd/telnetd_daemon.c b/apps/netutils/telnetd/telnetd_daemon.c
new file mode 100644
index 000000000..7165ee49d
--- /dev/null
+++ b/apps/netutils/telnetd/telnetd_daemon.c
@@ -0,0 +1,349 @@
+/****************************************************************************
+ * netutils/telnetd/telnetd_daemon.c
+ *
+ * Copyright (C) 2012 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 Gregory Nutt 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/socket.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <sched.h>
+#include <errno.h>
+#include <debug.h>
+#include <netinet/in.h>
+
+#include <apps/netutils/telnetd.h>
+#include <apps/netutils/uiplib.h>
+
+#include "telnetd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* This structure is used to passed information to telnet daemon when it
+ * started.
+ */
+
+struct telnetd_common_s g_telnetdcommon;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: telnetd_daemon
+ *
+ * Description:
+ * This function is the Telnet daemon. It does not return (unless an
+ * error occurs).
+ *
+ * Parameters:
+ * Standard task start up arguments.
+ *
+ * Return:
+ * Does not return unless an error occurs.
+ *
+ ****************************************************************************/
+
+static int telnetd_daemon(int argc, char *argv[])
+{
+ FAR struct telnetd_s *daemon;
+ struct sockaddr_in myaddr;
+#ifdef CONFIG_NET_HAVE_SOLINGER
+ struct linger ling;
+#endif
+ socklen_t addrlen;
+ FAR char *devpath;
+ pid_t pid;
+ int listensd;
+ int acceptsd;
+ int drvrfd;
+#ifdef CONFIG_NET_HAVE_REUSEADDR
+ int optval;
+#endif
+
+ /* Get daemon startup info */
+
+ daemon = g_telnetdcommon.daemon;
+ g_telnetdcommon.daemon = NULL;
+ sem_post(&g_telnetdcommon.startsem);
+ DEBUGASSERT(daemon != NULL);
+
+ /* Create a new TCP socket to use to listen for connections */
+
+ listensd = socket(PF_INET, SOCK_STREAM, 0);
+ if (listensd < 0)
+ {
+ int errval = errno;
+ ndbg("socket failure: %d\n", errval);
+ return -errval;
+ }
+
+ /* Set socket to reuse address */
+
+#ifdef CONFIG_NET_HAVE_REUSEADDR
+ optval = 1;
+ if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0)
+ {
+ ndbg("setsockopt SO_REUSEADDR failure: %d\n", errno);
+ goto errout_with_socket;
+ }
+#endif
+
+ /* Bind the socket to a local address */
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_port = daemon->port;
+ myaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(listensd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0)
+ {
+ ndbg("bind failure: %d\n", errno);
+ goto errout_with_socket;
+ }
+
+ /* Listen for connections on the bound TCP socket */
+
+ if (listen(listensd, 5) < 0)
+ {
+ ndbg("listen failure %d\n", errno);
+ goto errout_with_socket;
+ }
+
+ /* Now go silent */
+
+#ifndef CONFIG_DEBUG
+ close(0);
+ close(1);
+ close(2);
+#endif
+
+ /* Begin accepting connections */
+
+ for (;;)
+ {
+ nvdbg("Accepting connections on port %d\n", ntohs(daemon->port));
+
+ addrlen = sizeof(struct sockaddr_in);
+ acceptsd = accept(listensd, (struct sockaddr*)&myaddr, &addrlen);
+ if (acceptsd < 0)
+ {
+ ndbg("accept failed: %d\n", errno);
+ goto errout_with_socket;
+ }
+
+ /* Configure to "linger" until all data is sent when the socket is closed */
+
+#ifdef CONFIG_NET_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)
+ {
+ ndbg("setsockopt failed: %d\n", errno);
+ goto errout_with_acceptsd;
+ }
+#endif
+
+ /* Create a character device to "wrap" the accepted socket descriptor */
+
+ nvdbg("Creating the telnet driver\n");
+ devpath = telnetd_driver(acceptsd, daemon);
+ if (devpath < 0)
+ {
+ ndbg("telnetd_driver failed\n");
+ goto errout_with_acceptsd;
+ }
+
+ /* Open the driver */
+
+ nvdbg("Opening the telnet driver\n");
+ drvrfd = open(devpath, O_RDWR);
+ if (drvrfd < 0)
+ {
+ ndbg("Failed to open %s: %d\n", devpath, errno);
+ goto errout_with_acceptsd;
+ }
+
+ /* We can now free the driver string */
+
+ free(devpath);
+
+ /* Use this driver as stdin, stdout, and stderror */
+
+ (void)dup2(drvrfd, 0);
+ (void)dup2(drvrfd, 1);
+ (void)dup2(drvrfd, 2);
+
+ /* And we can close our original driver fd */
+
+ if (drvrfd > 2)
+ {
+ close(drvrfd);
+ }
+
+ /* Create a task to handle the connection. The created task
+ * will inherit the new stdin, stdout, and stderr.
+ */
+
+ nvdbg("Starting the telnet session\n");
+ pid = TASK_CREATE("Telnet session", daemon->priority, daemon->stacksize,
+ daemon->entry, NULL);
+ if (pid < 0)
+ {
+ ndbg("Failed start the telnet session: %d\n", errno);
+ goto errout_with_acceptsd;
+ }
+
+ /* Forget about the connection. */
+
+ close(0);
+ close(1);
+ close(2);
+ }
+
+errout_with_acceptsd:
+ close(acceptsd);
+
+errout_with_socket:
+ close(listensd);
+ free(daemon);
+ return 1;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: telnetd_start
+ *
+ * Description:
+ * Start the telnet daemon.
+ *
+ * Parameters:
+ * config A pointer to a configuration structure that characterizes the
+ * telnet daemon. This configuration structure may be defined
+ * on the caller's stack because it is not retained by the
+ * daemon.
+ *
+ * Return:
+ * The process ID (pid) of the new telnet daemon is returned on
+ * success; A negated errno is returned if the daemon was not successfully
+ * started.
+ *
+ ****************************************************************************/
+
+int telnetd_start(FAR struct telnetd_config_s *config)
+{
+ FAR struct telnetd_s *daemon;
+ pid_t pid;
+ int ret;
+
+ /* Allocate a state structure for the new daemon */
+
+ daemon = (FAR struct telnetd_s *)malloc(sizeof(struct telnetd_s));
+ if (!daemon)
+ {
+ return -ENOMEM;
+ }
+
+ /* Initialize the daemon structure */
+
+ daemon->port = config->d_port;
+ daemon->priority = config->t_priority;
+ daemon->stacksize = config->t_stacksize;
+ daemon->entry = config->t_entry;
+
+ /* Initialize the common structure if this is the first daemon */
+
+ if (g_telnetdcommon.ndaemons < 1)
+ {
+ sem_init(&g_telnetdcommon.startsem, 0, 0);
+ sem_init(&g_telnetdcommon.exclsem, 0, 1);
+ g_telnetdcommon.minor = 0;
+ }
+
+ /* Then start the new daemon */
+
+ g_telnetdcommon.daemon = daemon;
+ pid = TASK_CREATE("Telnet daemon", config->d_priority, config->d_stacksize,
+ telnetd_daemon, NULL);
+ if (pid < 0)
+ {
+ int errval = errno;
+ free(daemon);
+ ndbg("Failed to start the telnet daemon: %d\n", errval);
+ return -errval;
+ }
+
+ /* Then wait for the daemon to start and complete the handshake */
+
+ do
+ {
+ ret = sem_wait(&g_telnetdcommon.startsem);
+
+ /* The only expected error condition is for sem_wait to be awakened by
+ * a receipt of a signal.
+ */
+
+ if (ret < 0)
+ {
+ DEBUGASSERT(errno == -EINTR);
+ }
+ }
+ while (ret < 0);
+
+ /* Return success */
+
+ return pid;
+}
diff --git a/apps/netutils/telnetd/telnetd_driver.c b/apps/netutils/telnetd/telnetd_driver.c
new file mode 100644
index 000000000..efa693cdb
--- /dev/null
+++ b/apps/netutils/telnetd/telnetd_driver.c
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * apps/netutils/telnetd_driver.c
+ *
+ * Copyright (C) 2008-2 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * This is a leverage of similar logic from uIP which has a compatible BSD
+ * license:
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * 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 of the Institute, 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 INSTITUTE 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 INSTITUTE 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/socket.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <poll.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include <debug.h>
+
+#include <net/psock.h>
+
+#include <apps/netutils/telnetd.h>
+#include <apps/netutils/uiplib.h>
+
+#include "telnetd.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+
+#define TELNET_IAC 255
+#define TELNET_WILL 251
+#define TELNET_WONT 252
+#define TELNET_DO 253
+#define TELNET_DONT 254
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+/* The state of the telnet parser */
+
+enum telnetd_state_e
+{
+ STATE_NORMAL = 0,
+ STATE_IAC,
+ STATE_WILL,
+ STATE_WONT,
+ STATE_DO,
+ STATE_DONT
+};
+
+/* This structure describes the internal state of the driver */
+
+struct telnetd_dev_s
+{
+ sem_t td_exclsem; /* Enforces mutually exclusive access */
+ uint8_t td_state; /* (See telnetd_state_e) */
+ uint8_t td_pending; /* Number of valid, pending bytes in the rxbuffer */
+ uint8_t td_offset; /* Offset to the valid, pending bytes in the rxbuffer */
+ uint8_t td_crefs; /* The number of open references to the session */
+ FAR struct socket *td_psock; /* A reference to the internal socket structure */
+ char td_rxbuffer[CONFIG_TELNETD_IOBUFFER_SIZE];
+ char td_txbuffer[CONFIG_TELNETD_IOBUFFER_SIZE];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+/* Support functions */
+
+#ifdef CONFIG_TELNETD_DUMPBUFFER
+static inline void telnetd_dumpbuffer(FAR const char *msg,
+ FAR const char *buffer, unsigned int nbytes)
+#else
+# define telnetd_dumpbuffer(msg,buffer,nbytes)
+#endif
+static void telnetd_getchar(struct telnetd_dev_s *priv, uint8_t ch,
+ FAR char *dest, int *nread);
+static ssize_t telnetd_receive(struct telnetd_dev_s *priv, FAR const char *src,
+ size_t srclen, FAR char *dest, size_t destlen);
+static bool telnetd_putchar(struct telnetd_dev_s *priv, uint8_t ch,
+ int *nwritten);
+static void telnetd_sendopt(struct telnetd_dev_s *priv, uint8_t option,
+ uint8_t value);
+
+/* Character driver methods */
+
+static int telnetd_open(FAR struct file *filep);
+static int telnetd_close(FAR struct file *filep);
+static ssize_t telnetd_read(FAR struct file *, FAR char *, size_t);
+static ssize_t telnetd_write(FAR struct file *, FAR const char *, size_t);
+static int telnetd_ioctl(FAR struct file *filep, int cmd,
+ unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_telnetdfops =
+{
+ telnetd_open, /* open */
+ telnetd_close, /* close */
+ telnetd_read, /* read */
+ telnetd_write, /* write */
+ 0, /* seek */
+ telnetd_ioctl /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , 0 /* poll */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: telnetd_dumpbuffer
+ *
+ * Description:
+ * Dump a buffer of data (debug only)
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_TELNETD_DUMPBUFFER
+static inline void telnetd_dumpbuffer(FAR const char *msg,
+ FAR const char *buffer,
+ unsigned int nbytes)
+{
+ /* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_NET have to be
+ * defined or the following does nothing.
+ */
+
+ nvdbgdumpbuffer(msg, (FAR const uint8_t*)buffer, nbytes);
+}
+#endif
+
+/****************************************************************************
+ * Name: telnetd_getchar
+ *
+ * Description:
+ * Get another character for the user received buffer from the RX buffer
+ *
+ ****************************************************************************/
+
+static void telnetd_getchar(struct telnetd_dev_s *priv, uint8_t ch,
+ FAR char *dest, int *nread)
+{
+ register int index;
+
+ /* Ignore carriage returns */
+
+ if (ch != ISO_cr)
+ {
+ /* Add all other characters to the destination buffer */
+
+ index = *nread;
+ dest[index++] = ch;
+ *nread = index;
+ }
+}
+
+/****************************************************************************
+ * Name: telnetd_receive
+ *
+ * Description:
+ * Process a received telenet buffer
+ *
+ ****************************************************************************/
+
+static ssize_t telnetd_receive(struct telnetd_dev_s *priv, FAR const char *src,
+ size_t srclen, FAR char *dest, size_t destlen)
+{
+ int nread;
+ uint8_t ch;
+
+ for (nread = 0; srclen > 0 && nread < destlen; srclen--)
+ {
+ ch = *src++;
+ nvdbg("ch=%02x state=%d\n", ch, priv->td_state);
+
+ switch (priv->td_state)
+ {
+ case STATE_IAC:
+ if (ch == TELNET_IAC)
+ {
+ telnetd_getchar(priv, ch, dest, &nread);
+ priv->td_state = STATE_NORMAL;
+ }
+ else
+ {
+ switch (ch)
+ {
+ case TELNET_WILL:
+ priv->td_state = STATE_WILL;
+ break;
+
+ case TELNET_WONT:
+ priv->td_state = STATE_WONT;
+ break;
+
+ case TELNET_DO:
+ priv->td_state = STATE_DO;
+ break;
+
+ case TELNET_DONT:
+ priv->td_state = STATE_DONT;
+ break;
+
+ default:
+ priv->td_state = STATE_NORMAL;
+ break;
+ }
+ }
+ break;
+
+ case STATE_WILL:
+ /* Reply with a DONT */
+
+ telnetd_sendopt(priv, TELNET_DONT, ch);
+ priv->td_state = STATE_NORMAL;
+ break;
+
+ case STATE_WONT:
+ /* Reply with a DONT */
+
+ telnetd_sendopt(priv, TELNET_DONT, ch);
+ priv->td_state = STATE_NORMAL;
+ break;
+
+ case STATE_DO:
+ /* Reply with a WONT */
+
+ telnetd_sendopt(priv, TELNET_WONT, ch);
+ priv->td_state = STATE_NORMAL;
+ break;
+
+ case STATE_DONT:
+ /* Reply with a WONT */
+
+ telnetd_sendopt(priv, TELNET_WONT, ch);
+ priv->td_state = STATE_NORMAL;
+ break;
+
+ case STATE_NORMAL:
+ if (ch == TELNET_IAC)
+ {
+ priv->td_state = STATE_IAC;
+ }
+ else
+ {
+ telnetd_getchar(priv, ch, dest, &nread);
+ }
+ break;
+ }
+ }
+
+ /* We get here if (1) all of the received bytes have been processed, or
+ * (2) if the user's buffer has become full.
+ */
+
+ if (srclen > 0)
+ {
+ /* Remember where we left off. These bytes will be returned the next
+ * time that telnetd_read() is called.
+ */
+
+ priv->td_pending = srclen;
+ priv->td_offset = (src - priv->td_rxbuffer);
+ }
+ else
+ {
+ /* All of the received bytes were consumed */
+
+ priv->td_pending = 0;
+ priv->td_offset = 0;
+ }
+
+ return nread;
+}
+
+/****************************************************************************
+ * Name: telnetd_putchar
+ *
+ * Description:
+ * Put another character from the user buffer to the TX buffer.
+ *
+ ****************************************************************************/
+
+static bool telnetd_putchar(struct telnetd_dev_s *priv, uint8_t ch,
+ int *nread)
+{
+ register int index;
+ bool ret = false;
+
+ /* Ignore carriage returns (we will put these in automatically as necesary) */
+
+ if (ch != ISO_cr)
+ {
+ /* Add all other characters to the destination buffer */
+
+ index = *nread;
+ priv->td_txbuffer[index++] = ch;
+
+ /* Check for line feeds */
+
+ if (ch == ISO_nl)
+ {
+ /* Now add the carriage return */
+
+ priv->td_txbuffer[index++] = ISO_cr;
+ priv->td_txbuffer[index++] = '\0';
+
+ /* End of line */
+
+ ret = true;
+ }
+
+ *nread = index;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: telnetd_sendopt
+ *
+ * Description:
+ * Send the telnet option bytes
+ *
+ ****************************************************************************/
+
+static void telnetd_sendopt(struct telnetd_dev_s *priv, uint8_t option,
+ uint8_t value)
+{
+ uint8_t optbuf[4];
+ optbuf[0] = TELNET_IAC;
+ optbuf[1] = option;
+ optbuf[2] = value;
+ optbuf[3] = 0;
+
+ telnetd_dumpbuffer("Send optbuf", optbuf, 4);
+ if (psock_send(priv->td_psock, optbuf, 4, 0) < 0)
+ {
+ ndbg("Failed to send TELNET_IAC\n");
+ }
+}
+
+/****************************************************************************
+ * Name: telnetd_open
+ ****************************************************************************/
+
+static int telnetd_open(FAR struct file *filep)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct telnetd_dev_s *priv = inode->i_private;
+ int tmp;
+ int ret;
+
+ nvdbg("td_crefs: %d\n", priv->td_crefs);
+
+ /* O_NONBLOCK is not supported */
+
+ if (filep->f_oflags & O_NONBLOCK)
+ {
+ ret = -ENOSYS;
+ goto errout;
+ }
+
+ /* Get exclusive access to the device structures */
+
+ ret = sem_wait(&priv->td_exclsem);
+ if (ret < 0)
+ {
+ ret = -errno;
+ goto errout;
+ }
+
+ /* Increment the count of references to the device. If this the first
+ * time that the driver has been opened for this device, then initialize
+ * the device.
+ */
+
+ tmp = priv->td_crefs + 1;
+ if (tmp > 255)
+ {
+ /* More than 255 opens; uint8_t would overflow to zero */
+
+ ret = -EMFILE;
+ goto errout_with_sem;
+ }
+
+ /* Save the new open count on success */
+
+ priv->td_crefs = tmp;
+ ret = OK;
+
+errout_with_sem:
+ sem_post(&priv->td_exclsem);
+
+errout:
+ return ret;
+}
+
+/****************************************************************************
+ * Name: telnetd_close
+ ****************************************************************************/
+
+static int telnetd_close(FAR struct file *filep)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct telnetd_dev_s *priv = inode->i_private;
+ int ret;
+
+ nvdbg("td_crefs: %d\n", priv->td_crefs);
+
+ /* Get exclusive access to the device structures */
+
+ ret = sem_wait(&priv->td_exclsem);
+ if (ret < 0)
+ {
+ ret = -errno;
+ goto errout;
+ }
+
+ /* Decrement the references to the driver. If the reference count will
+ * decrement to 0, then uninitialize the driver.
+ */
+
+ if (priv->td_crefs > 1)
+ {
+ priv->td_crefs--;
+ sem_post(&priv->td_exclsem);
+ }
+ else
+ {
+ psock_close(priv->td_psock);
+ sem_post(&priv->td_exclsem);
+ sem_destroy(&priv->td_exclsem);
+ free(priv);
+ }
+
+ ret = OK;
+
+errout:
+ return ret;
+}
+
+/****************************************************************************
+ * Name: telnetd_read
+ ****************************************************************************/
+
+static ssize_t telnetd_read(FAR struct file *filep, FAR char *buffer, size_t len)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct telnetd_dev_s *priv = inode->i_private;
+ ssize_t ret;
+
+ /* First, handle the case where there are still valid bytes left in the
+ * I/O buffer from the last time that read was called.
+ */
+
+ if (priv->td_pending > 0)
+ {
+ FAR const char *src = &priv->td_rxbuffer[priv->td_offset];
+ ret = telnetd_receive(priv, src, priv->td_pending, buffer, len);
+ }
+
+ /* Read a buffer of data from the telnet client */
+
+ else
+ {
+ ret = psock_recv(priv->td_psock, priv->td_rxbuffer,
+ CONFIG_TELNETD_IOBUFFER_SIZE, 0);
+ if (ret > 0)
+ {
+ /* Process the received telnet data */
+
+ telnetd_dumpbuffer("Received buffer", priv->td_rxbuffer, ret);
+ ret = telnetd_receive(priv, priv->td_rxbuffer, ret, buffer, len);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: telnetd_write
+ ****************************************************************************/
+
+static ssize_t telnetd_write(FAR struct file *filep, FAR const char *buffer, size_t len)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct telnetd_dev_s *priv = inode->i_private;
+ FAR const char *src = buffer;
+ ssize_t nsent;
+ ssize_t ret;
+ int ncopied;
+ char ch;
+ bool eol;
+
+ /* Process each character from the user buffer */
+
+ for (nsent = 0, ncopied = 0; len > 0; len--)
+ {
+ /* Get the next character from the user buffer */
+
+ ch = *src++;
+
+ /* Add the character to the TX buffer */
+
+ eol = telnetd_putchar(priv, ch, &ncopied);
+
+ /* Was that the end of a line? */
+
+ if (eol)
+ {
+ /* Yes... send the data now */
+
+ ret = psock_send(priv->td_psock, priv->td_txbuffer, ncopied, 0);
+ if (ret < 0)
+ {
+ ndbg("Failed to send response: %s\n", priv->td_txbuffer);
+ }
+
+ /* Reset the index to the beginning of the TX buffer. Remember
+ * the total number of bytes sent;
+ */
+
+ nsent += ret;
+ ncopied = 0;
+ }
+ }
+
+ /* Send anything remaining in the TX buffer */
+
+ if (ncopied > 0)
+ {
+ ret = psock_send(priv->td_psock, priv->td_txbuffer, ncopied, 0);
+ if (ret < 0)
+ {
+ ndbg("Failed to send response: %s\n", priv->td_txbuffer);
+ }
+ nsent += ret;
+ }
+
+ return nsent;
+}
+
+/****************************************************************************
+ * Name: telnetd_poll
+ ****************************************************************************/
+
+static int telnetd_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+#if 0 /* No ioctl commands are yet supported */
+ struct inode *inode = filep->f_inode;
+ struct cdcacm_dev_s *priv = inode->i_private;
+ int ret = OK;
+
+ switch (cmd)
+ {
+ /* Add ioctl commands here */
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ return ret;
+#else
+ return -ENOTTY;
+#endif
+}
+
+/****************************************************************************
+ * Name: telnetd_poll
+ ****************************************************************************/
+
+#if 0 /* Not used by this driver */
+static int telnetd_poll(FAR struct file *filep, FAR struct pollfd *fds,
+ bool setup)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct telnetd_dev_s *priv = inode->i_private;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: telnetd_driver
+ *
+ * Description:
+ * Create a character driver to "wrap" the telnet session. This function
+ * will select and return a unique path for the new telnet device.
+ *
+ * Parameters:
+ * sd - The socket descriptor that represents the new telnet connection.
+ * daemon - A pointer to the structure representing the overall state of
+ * this instance of the telnet daemon.
+ *
+ * Return:
+ * An allocated string represent the full path to the created driver. The
+ * receiver of the string must de-allocate this memory when it is no longer
+ * needed. NULL is returned on a failure.
+ *
+ ****************************************************************************/
+
+FAR char *telnetd_driver(int sd, FAR struct telnetd_s *daemon)
+{
+ FAR struct telnetd_dev_s *priv;
+ FAR char *devpath = NULL;
+ int minor;
+ int ret;
+
+ /* Allocate instance data for this driver */
+
+ priv = (FAR struct telnetd_dev_s*)malloc(sizeof(struct telnetd_dev_s));
+ if (!priv)
+ {
+ ndbg("Failed to allocate the driver data structure\n");
+ return NULL;
+ }
+
+ /* Initialize the allocated driver instance */
+
+ priv->td_psock = sockfd_socket(sd);
+ priv->td_state = STATE_NORMAL;
+ priv->td_crefs = 0;
+ priv->td_pending = 0;
+ priv->td_offset = 0;
+
+ if (!priv->td_psock)
+ {
+ ndbg("Failed to convert sd=%d to a socket structure\n");
+ goto errout_with_dev;
+ }
+
+ /* Allocation a unique minor device number of the telnet drvier */
+
+ do
+ {
+ ret = sem_wait(&g_telnetdcommon.exclsem);
+ if (ret < 0 && errno != -EINTR)
+ {
+ goto errout_with_dev;
+ }
+ }
+ while (ret < 0);
+
+ minor = g_telnetdcommon.minor;
+ g_telnetdcommon.minor++;
+ sem_post(&g_telnetdcommon.exclsem);
+
+ /* Create a path and name for the driver. */
+
+ ret = asprintf(&devpath, "/dev/telnetd%d", minor);
+ if (ret < 0)
+ {
+ ndbg("Failed to allocate the driver path\n");
+ goto errout_with_dev;
+ }
+
+ /* Register the driver */
+
+ ret = register_driver(devpath, &g_telnetdfops, 0666, priv);
+ if (ret < 0)
+ {
+ ndbg("Failed to register the driver %s: %d\n", ret);
+ goto errout_with_devpath;
+ }
+
+ /* Return the path to the new telnet driver */
+
+ return devpath;
+
+errout_with_devpath:
+ free(devpath);
+errout_with_dev:
+ free(priv);
+ return NULL;
+}
+
+
+
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 271d7fb89..72024519b 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -2408,3 +2408,5 @@
sub-directory: By making libboard.a a "phony" target, libboard.a should
always rebuilt (the end result is worth the small increase in build time)
(submitted by Mike Smith).
+ * include/net/psock.h: A new low level socket interface that allows the OS
+ to use the socket interface without having a socket descriptor.
diff --git a/nuttx/include/net/psock.h b/nuttx/include/net/psock.h
new file mode 100644
index 000000000..26691d5df
--- /dev/null
+++ b/nuttx/include/net/psock.h
@@ -0,0 +1,312 @@
+/****************************************************************************
+ * include/net/psock.h
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 __NET_PSOCK_H
+#define __NET_PSOCK_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+
+#ifdef CONFIG_NET
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Function: sockfd_socket
+ *
+ * Description:
+ * Given a socket descriptor, return the underly NuttX-specific socket
+ * structure.
+ *
+ * Parameters:
+ * psock Socket instance
+ *
+ * Returned Value:
+ * 0 on success; -1 on error with errno set appropriately.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+struct socket;
+EXTERN FAR struct socket *sockfd_socket(int sockfd);
+
+/****************************************************************************
+ * Function: psock_close
+ *
+ * Description:
+ * Performs the close operation on a socket instance
+ *
+ * Parameters:
+ * psock Socket instance
+ *
+ * Returned Value:
+ * 0 on success; -1 on error with errno set appropriately.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+struct socket;
+EXTERN int psock_close(FAR struct socket *psock);
+
+/****************************************************************************
+ * Function: psock_send
+ *
+ * Description:
+ * The send() call may be used only when the socket is in a connected state
+ * (so that the intended recipient is known). The only difference between
+ * send() and write() is the presence of flags. With zero flags parameter,
+ * send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is
+ * equivalent to sendto(sockfd,buf,len,flags,NULL,0).
+ *
+ * Parameters:
+ * psock And instance of the internal socket structure.
+ * buf Data to send
+ * len Length of data to send
+ * flags Send flags
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately:
+ *
+ * EAGAIN or EWOULDBLOCK
+ * The socket is marked non-blocking and the requested operation
+ * would block.
+ * EBADF
+ * An invalid descriptor was specified.
+ * ECONNRESET
+ * Connection reset by peer.
+ * EDESTADDRREQ
+ * The socket is not connection-mode, and no peer address is set.
+ * EFAULT
+ * An invalid user space address was specified for a parameter.
+ * EINTR
+ * A signal occurred before any data was transmitted.
+ * EINVAL
+ * Invalid argument passed.
+ * EISCONN
+ * The connection-mode socket was connected already but a recipient
+ * was specified. (Now either this error is returned, or the recipient
+ * specification is ignored.)
+ * EMSGSIZE
+ * The socket type requires that message be sent atomically, and the
+ * size of the message to be sent made this impossible.
+ * ENOBUFS
+ * The output queue for a network interface was full. This generally
+ * indicates that the interface has stopped sending, but may be
+ * caused by transient congestion.
+ * ENOMEM
+ * No memory available.
+ * ENOTCONN
+ * The socket is not connected, and no target has been given.
+ * ENOTSOCK
+ * The argument s is not a socket.
+ * EOPNOTSUPP
+ * Some bit in the flags argument is inappropriate for the socket
+ * type.
+ * EPIPE
+ * The local end has been shut down on a connection oriented socket.
+ * In this case the process will also receive a SIGPIPE unless
+ * MSG_NOSIGNAL is set.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+struct socket;
+EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf,
+ size_t len, int flags);
+
+/****************************************************************************
+ * Function: psock_sendto
+ *
+ * Description:
+ * If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
+ * socket, the parameters to and 'tolen' are ignored (and the error EISCONN
+ * may be returned when they are not NULL and 0), and the error ENOTCONN is
+ * returned when the socket was not actually connected.
+ *
+ * Parameters:
+ * psock A pointer to a NuttX-specific, internal socket structure
+ * buf Data to send
+ * len Length of data to send
+ * flags Send flags
+ * to Address of recipient
+ * tolen The length of the address structure
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately:
+ *
+ * EAGAIN or EWOULDBLOCK
+ * The socket is marked non-blocking and the requested operation
+ * would block.
+ * EBADF
+ * An invalid descriptor was specified.
+ * ECONNRESET
+ * Connection reset by peer.
+ * EDESTADDRREQ
+ * The socket is not connection-mode, and no peer address is set.
+ * EFAULT
+ * An invalid user space address was specified for a parameter.
+ * EINTR
+ * A signal occurred before any data was transmitted.
+ * EINVAL
+ * Invalid argument passed.
+ * EISCONN
+ * The connection-mode socket was connected already but a recipient
+ * was specified. (Now either this error is returned, or the recipient
+ * specification is ignored.)
+ * EMSGSIZE
+ * The socket type requires that message be sent atomically, and the
+ * size of the message to be sent made this impossible.
+ * ENOBUFS
+ * The output queue for a network interface was full. This generally
+ * indicates that the interface has stopped sending, but may be
+ * caused by transient congestion.
+ * ENOMEM
+ * No memory available.
+ * ENOTCONN
+ * The socket is not connected, and no target has been given.
+ * ENOTSOCK
+ * The argument s is not a socket.
+ * EOPNOTSUPP
+ * Some bit in the flags argument is inappropriate for the socket
+ * type.
+ * EPIPE
+ * The local end has been shut down on a connection oriented socket.
+ * In this case the process will also receive a SIGPIPE unless
+ * MSG_NOSIGNAL is set.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+struct socket;
+struct sockaddr;
+EXTERN ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags, FAR const struct sockaddr *to,
+ socklen_t tolen);
+
+/****************************************************************************
+ * Function: psock_recvfrom
+ *
+ * Description:
+ * recvfrom() receives messages from a socket, and may be used to receive
+ * data on a socket whether or not it is connection-oriented.
+ *
+ * If from is not NULL, and the underlying protocol provides the source
+ * address, this source address is filled in. The argument fromlen
+ * initialized to the size of the buffer associated with from, and modified
+ * on return to indicate the actual size of the address stored there.
+ *
+ * Parameters:
+ * psock A pointer to a NuttX-specific, internal socket structure
+ * buf Buffer to receive data
+ * len Length of buffer
+ * flags Receive flags
+ * from Address of source (may be NULL)
+ * fromlen The length of the address structure
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately:
+ *
+ * EAGAIN
+ * The socket is marked non-blocking and the receive operation would block,
+ * or a receive timeout had been set and the timeout expired before data
+ * was received.
+ * EBADF
+ * The argument sockfd is an invalid descriptor.
+ * ECONNREFUSED
+ * A remote host refused to allow the network connection (typically because
+ * it is not running the requested service).
+ * EFAULT
+ * The receive buffer pointer(s) point outside the process's address space.
+ * EINTR
+ * The receive was interrupted by delivery of a signal before any data were
+ * available.
+ * EINVAL
+ * Invalid argument passed.
+ * ENOMEM
+ * Could not allocate memory.
+ * ENOTCONN
+ * The socket is associated with a connection-oriented protocol and has
+ * not been connected.
+ * ENOTSOCK
+ * The argument sockfd does not refer to a socket.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+struct socket;
+struct sockaddr;
+EXTERN ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf,
+ size_t len, int flags,FAR struct sockaddr *from,
+ FAR socklen_t *fromlen);
+
+#define psock_recv(psock,buf,len,flags) psock_recvfrom(psock,buf,len,flags,NULL,0)
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* CONFIG_NET */
+#endif /* __NET_PSOCK_H */
diff --git a/nuttx/net/net_close.c b/nuttx/net/net_close.c
index ca2e2999c..cf1c36bfe 100644
--- a/nuttx/net/net_close.c
+++ b/nuttx/net/net_close.c
@@ -1,8 +1,8 @@
/****************************************************************************
* net/net_close.c
*
- * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -199,10 +199,10 @@ static inline void netclose_disconnect(FAR struct socket *psock)
****************************************************************************/
/****************************************************************************
- * Function: net_closesocket
+ * Function: psock_close
*
* Description:
- * Performs the close operation on asocket instance
+ * Performs the close operation on a socket instance
*
* Parameters:
* psock Socket instance
@@ -214,7 +214,7 @@ static inline void netclose_disconnect(FAR struct socket *psock)
*
****************************************************************************/
-int net_closesocket(FAR struct socket *psock)
+int psock_close(FAR struct socket *psock)
{
int err;
@@ -324,7 +324,7 @@ errout:
int net_close(int sockfd)
{
- return net_closesocket(sockfd_socket(sockfd));
+ return psock_close(sockfd_socket(sockfd));
}
#endif /* CONFIG_NET */
diff --git a/nuttx/net/net_internal.h b/nuttx/net/net_internal.h
index e3498cd44..4046070ab 100644
--- a/nuttx/net/net_internal.h
+++ b/nuttx/net/net_internal.h
@@ -1,8 +1,8 @@
/****************************************************************************
* net/net_internal.h
*
- * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -48,6 +48,7 @@
#include <time.h>
#include <nuttx/net.h>
+#include <net/psock.h>
#include <net/uip/uip.h>
/****************************************************************************
@@ -157,7 +158,7 @@ EXTERN FAR struct socket *sockfd_socket(int sockfd);
/* net_close.c ***************************************************************/
-EXTERN int net_closesocket(FAR struct socket *psock);
+EXTERN int psock_close(FAR struct socket *psock);
/* sockopt support ***********************************************************/
@@ -206,6 +207,11 @@ EXTERN void arptimer_init(void);
# define arptimer_init()
#endif
+/* send.c ********************************************************************/
+
+EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf,
+ size_t len, int flags);
+
#undef EXTERN
#if defined(__cplusplus)
}
diff --git a/nuttx/net/net_poll.c b/nuttx/net/net_poll.c
index fa63c8d45..da953fc9f 100644
--- a/nuttx/net/net_poll.c
+++ b/nuttx/net/net_poll.c
@@ -1,8 +1,8 @@
/****************************************************************************
* net/net_poll.c
*
- * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/nuttx/net/net_sockets.c b/nuttx/net/net_sockets.c
index a1e8f15b0..31c1709d7 100644
--- a/nuttx/net/net_sockets.c
+++ b/nuttx/net/net_sockets.c
@@ -1,8 +1,8 @@
/****************************************************************************
* net/net_sockets.c
*
- * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -186,7 +186,7 @@ int net_releaselist(FAR struct socketlist *list)
if (crefs <= 0)
{
/* Close each open socket in the list
- * REVISIT: net_closesocket() will attempt to use semaphores.
+ * REVISIT: psock_close() will attempt to use semaphores.
* If we actually are in the IDLE thread, then could this cause
* problems? Probably not, it the task has exited and crefs is
* zero, then there probably could not be a contender for the
@@ -198,7 +198,7 @@ int net_releaselist(FAR struct socketlist *list)
FAR struct socket *psock = &list->sl_sockets[ndx];
if (psock->s_crefs > 0)
{
- (void)net_closesocket(psock);
+ (void)psock_close(psock);
}
}
diff --git a/nuttx/net/recv.c b/nuttx/net/recv.c
index 3d5b82f2c..1571a7377 100644
--- a/nuttx/net/recv.c
+++ b/nuttx/net/recv.c
@@ -1,8 +1,8 @@
/****************************************************************************
* net/recv.c
*
- * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index d9039b91b..f1f08d66d 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -1,8 +1,8 @@
/****************************************************************************
* net/recvfrom.c
*
- * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -988,7 +988,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
****************************************************************************/
/****************************************************************************
- * Function: recvfrom
+ * Function: psock_recvfrom
*
* Description:
* recvfrom() receives messages from a socket, and may be used to receive
@@ -1000,7 +1000,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* on return to indicate the actual size of the address stored there.
*
* Parameters:
- * sockfd Socket descriptor of socket
+ * psock A pointer to a NuttX-specific, internal socket structure
* buf Buffer to receive data
* len Length of buffer
* flags Receive flags
@@ -1039,11 +1039,10 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
*
****************************************************************************/
-ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
- FAR struct sockaddr *from, FAR socklen_t *fromlen)
+ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ int flags,FAR struct sockaddr *from,
+ FAR socklen_t *fromlen)
{
- FAR struct socket *psock;
-
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
#ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in6 *infrom = (struct sockaddr_in6 *)from;
@@ -1065,10 +1064,8 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
}
#endif
- /* Get the underlying socket structure */
/* Verify that the sockfd corresponds to valid, allocated socket */
- psock = sockfd_socket(sockfd);
if (!psock || psock->s_crefs <= 0)
{
err = EBADF;
@@ -1136,4 +1133,70 @@ errout:
return ERROR;
}
+/****************************************************************************
+ * Function: recvfrom
+ *
+ * Description:
+ * recvfrom() receives messages from a socket, and may be used to receive
+ * data on a socket whether or not it is connection-oriented.
+ *
+ * If from is not NULL, and the underlying protocol provides the source
+ * address, this source address is filled in. The argument fromlen
+ * initialized to the size of the buffer associated with from, and modified
+ * on return to indicate the actual size of the address stored there.
+ *
+ * Parameters:
+ * sockfd Socket descriptor of socket
+ * buf Buffer to receive data
+ * len Length of buffer
+ * flags Receive flags
+ * from Address of source (may be NULL)
+ * fromlen The length of the address structure
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately:
+ *
+ * EAGAIN
+ * The socket is marked non-blocking and the receive operation would block,
+ * or a receive timeout had been set and the timeout expired before data
+ * was received.
+ * EBADF
+ * The argument sockfd is an invalid descriptor.
+ * ECONNREFUSED
+ * A remote host refused to allow the network connection (typically because
+ * it is not running the requested service).
+ * EFAULT
+ * The receive buffer pointer(s) point outside the process's address space.
+ * EINTR
+ * The receive was interrupted by delivery of a signal before any data were
+ * available.
+ * EINVAL
+ * Invalid argument passed.
+ * ENOMEM
+ * Could not allocate memory.
+ * ENOTCONN
+ * The socket is associated with a connection-oriented protocol and has
+ * not been connected.
+ * ENOTSOCK
+ * The argument sockfd does not refer to a socket.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
+ FAR struct sockaddr *from, FAR socklen_t *fromlen)
+{
+ FAR struct socket *psock;
+
+ /* Get the underlying socket structure */
+
+ psock = sockfd_socket(sockfd);
+
+ /* Then let psock_recvfrom() do all of the work */
+
+ return psock_recvfrom(psock, buf, len, flags, from, fromlen);
+}
+
#endif /* CONFIG_NET */
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index 4eceddffc..087b43351 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -1,8 +1,8 @@
/****************************************************************************
* net/send.c
*
- * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -336,7 +336,7 @@ end_wait:
****************************************************************************/
/****************************************************************************
- * Function: send
+ * Function: psock_send
*
* Description:
* The send() call may be used only when the socket is in a connected state
@@ -346,7 +346,7 @@ end_wait:
* equivalent to sendto(sockfd,buf,len,flags,NULL,0).
*
* Parameters:
- * sockfd Socket descriptor of socket
+ * psock And instance of the internal socket structure.
* buf Data to send
* len Length of data to send
* flags Send flags
@@ -399,9 +399,8 @@ end_wait:
*
****************************************************************************/
-ssize_t send(int sockfd, const void *buf, size_t len, int flags)
+ssize_t psock_send(FAR struct socket *psock, const void *buf, size_t len, int flags)
{
- FAR struct socket *psock = sockfd_socket(sockfd);
struct send_s state;
uip_lock_t save;
int err;
@@ -525,4 +524,73 @@ errout:
return ERROR;
}
+/****************************************************************************
+ * Function: send
+ *
+ * Description:
+ * The send() call may be used only when the socket is in a connected state
+ * (so that the intended recipient is known). The only difference between
+ * send() and write() is the presence of flags. With zero flags parameter,
+ * send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is
+ * equivalent to sendto(sockfd,buf,len,flags,NULL,0).
+ *
+ * Parameters:
+ * sockfd Socket descriptor of socket
+ * buf Data to send
+ * len Length of data to send
+ * flags Send flags
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately:
+ *
+ * EAGAIN or EWOULDBLOCK
+ * The socket is marked non-blocking and the requested operation
+ * would block.
+ * EBADF
+ * An invalid descriptor was specified.
+ * ECONNRESET
+ * Connection reset by peer.
+ * EDESTADDRREQ
+ * The socket is not connection-mode, and no peer address is set.
+ * EFAULT
+ * An invalid user space address was specified for a parameter.
+ * EINTR
+ * A signal occurred before any data was transmitted.
+ * EINVAL
+ * Invalid argument passed.
+ * EISCONN
+ * The connection-mode socket was connected already but a recipient
+ * was specified. (Now either this error is returned, or the recipient
+ * specification is ignored.)
+ * EMSGSIZE
+ * The socket type requires that message be sent atomically, and the
+ * size of the message to be sent made this impossible.
+ * ENOBUFS
+ * The output queue for a network interface was full. This generally
+ * indicates that the interface has stopped sending, but may be
+ * caused by transient congestion.
+ * ENOMEM
+ * No memory available.
+ * ENOTCONN
+ * The socket is not connected, and no target has been given.
+ * ENOTSOCK
+ * The argument s is not a socket.
+ * EOPNOTSUPP
+ * Some bit in the flags argument is inappropriate for the socket
+ * type.
+ * EPIPE
+ * The local end has been shut down on a connection oriented socket.
+ * In this case the process will also receive a SIGPIPE unless
+ * MSG_NOSIGNAL is set.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+ssize_t send(int sockfd, const void *buf, size_t len, int flags)
+{
+ return psock_send(sockfd_socket(sockfd), buf, len, flags);
+}
+
#endif /* CONFIG_NET && CONFIG_NET_TCP */
diff --git a/nuttx/net/sendto.c b/nuttx/net/sendto.c
index 8e2bf29b2..4e1f9015f 100644
--- a/nuttx/net/sendto.c
+++ b/nuttx/net/sendto.c
@@ -1,8 +1,8 @@
/****************************************************************************
* net/sendto.c
*
- * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -157,7 +157,7 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
****************************************************************************/
/****************************************************************************
- * Function: sendto
+ * Function: psock_sendto
*
* Description:
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
@@ -166,7 +166,7 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
* returned when the socket was not actually connected.
*
* Parameters:
- * sockfd Socket descriptor of socket
+ * psock A pointer to a NuttX-specific, internal socket structure
* buf Data to send
* len Length of data to send
* flags Send flags
@@ -221,10 +221,10 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
*
****************************************************************************/
-ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
- const struct sockaddr *to, socklen_t tolen)
+ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags, FAR const struct sockaddr *to,
+ socklen_t tolen)
{
- FAR struct socket *psock;
#ifdef CONFIG_NET_UDP
FAR struct uip_udp_conn *conn;
#ifdef CONFIG_NET_IPv6
@@ -245,7 +245,7 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
if (!to || !tolen)
{
#ifdef CONFIG_NET_TCP
- return send(sockfd, buf, len, flags);
+ return psock_send(psock, buf, len, flags);
#else
err = EINVAL;
goto errout;
@@ -264,10 +264,8 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
goto errout;
}
- /* Get the underlying socket structure */
- /* Verify that the sockfd corresponds to valid, allocated socket */
+ /* Verify that the psock corresponds to valid, allocated socket */
- psock = sockfd_socket(sockfd);
if (!psock || psock->s_crefs <= 0)
{
err = EBADF;
@@ -369,4 +367,83 @@ errout:
return ERROR;
}
+/****************************************************************************
+ * Function: sendto
+ *
+ * Description:
+ * If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
+ * socket, the parameters to and 'tolen' are ignored (and the error EISCONN
+ * may be returned when they are not NULL and 0), and the error ENOTCONN is
+ * returned when the socket was not actually connected.
+ *
+ * Parameters:
+ * sockfd Socket descriptor of socket
+ * buf Data to send
+ * len Length of data to send
+ * flags Send flags
+ * to Address of recipient
+ * tolen The length of the address structure
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately:
+ *
+ * EAGAIN or EWOULDBLOCK
+ * The socket is marked non-blocking and the requested operation
+ * would block.
+ * EBADF
+ * An invalid descriptor was specified.
+ * ECONNRESET
+ * Connection reset by peer.
+ * EDESTADDRREQ
+ * The socket is not connection-mode, and no peer address is set.
+ * EFAULT
+ * An invalid user space address was specified for a parameter.
+ * EINTR
+ * A signal occurred before any data was transmitted.
+ * EINVAL
+ * Invalid argument passed.
+ * EISCONN
+ * The connection-mode socket was connected already but a recipient
+ * was specified. (Now either this error is returned, or the recipient
+ * specification is ignored.)
+ * EMSGSIZE
+ * The socket type requires that message be sent atomically, and the
+ * size of the message to be sent made this impossible.
+ * ENOBUFS
+ * The output queue for a network interface was full. This generally
+ * indicates that the interface has stopped sending, but may be
+ * caused by transient congestion.
+ * ENOMEM
+ * No memory available.
+ * ENOTCONN
+ * The socket is not connected, and no target has been given.
+ * ENOTSOCK
+ * The argument s is not a socket.
+ * EOPNOTSUPP
+ * Some bit in the flags argument is inappropriate for the socket
+ * type.
+ * EPIPE
+ * The local end has been shut down on a connection oriented socket.
+ * In this case the process will also receive a SIGPIPE unless
+ * MSG_NOSIGNAL is set.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
+ FAR const struct sockaddr *to, socklen_t tolen)
+{
+ FAR struct socket *psock;
+
+ /* Get the underlying socket structure */
+
+ psock = sockfd_socket(sockfd);
+
+ /* And let psock_sendto do all of the work */
+
+ return psock_sendto(psock, buf, len, flags, to, tolen);
+}
+
#endif /* CONFIG_NET */