Add new psock layer; telnet session is now wrapped in a character device

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4347 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-01-30 21:29:59 +00:00
parent a11ad68eed
commit 622ac27bfa
27 changed files with 2373 additions and 782 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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
^^^^^^^^^^^^^^^

View File

@ -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

View File

@ -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.

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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/.

View File

@ -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))

View File

@ -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.

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

312
nuttx/include/net/psock.h Normal file
View File

@ -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 */

View File

@ -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 */

View File

@ -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)
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */