From 20c3067ff452e4e4604e11ec37479c50a4444de8 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 25 Nov 2007 16:50:16 +0000 Subject: Integrated uIP's TELNETD git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@408 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/ChangeLog | 2 + nuttx/Documentation/NuttX.html | 2 + nuttx/TODO | 2 - nuttx/include/net/uip/telnetd.h | 70 +++++ nuttx/netutils/telnetd/shell.c | 157 +++++++---- nuttx/netutils/telnetd/shell.h | 18 +- nuttx/netutils/telnetd/telnetd.c | 575 ++++++++++++++++++++++++--------------- nuttx/netutils/telnetd/telnetd.h | 53 ---- nuttx/netutils/webserver/httpd.c | 4 +- nuttx/netutils/webserver/httpd.h | 4 +- 10 files changed, 542 insertions(+), 345 deletions(-) create mode 100644 nuttx/include/net/uip/telnetd.h delete mode 100644 nuttx/netutils/telnetd/telnetd.h (limited to 'nuttx') diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 75202c115..90124431a 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -251,3 +251,5 @@ * Correct socket close logic -- needs to disconnect TCP socket on close * uIP webserver now seems to be fully functional * fs/ and lib/ subystem debug can not be selectively enabled/disabled + * Added vsnprintf + * Integrated uIP telnetd diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index 954ee19ee..17ec1169d 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -731,6 +731,8 @@ Other memory: * Correct socket close logic -- needs to disconnect TCP socket on close * uIP webserver now seems to be fully functional * fs/ and lib/ subystem debug can not be selectively enabled/disabled + * Added vsnprintf + * Integrated uIP telnetd diff --git a/nuttx/TODO b/nuttx/TODO index 197a966b0..4484be424 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -31,8 +31,6 @@ o C++ Support o Network - Did not implement send() and sendto() timeouts. Option is setable via setsockopt, but is not implemented. -- uIP's netutils/telnetd (and maybe others) are seriously broken. - Need to be re-written to use listen() and accept() - uIP's netutils/smtp, dpcpc, resolv, webclient -- untested - Should implement SOCK_RAW - Performance Improvements (uIP is not very fast): diff --git a/nuttx/include/net/uip/telnetd.h b/nuttx/include/net/uip/telnetd.h new file mode 100644 index 000000000..32247c206 --- /dev/null +++ b/nuttx/include/net/uip/telnetd.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * include/net/uip/telnetd.h + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This is a leverage of similar logic from uIP: + * + * Author: Adam Dunkels + * 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. + ****************************************************************************/ + +#ifndef __NET_UIP_TELNETD_H +#define __NET_UIP_TELNETD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Start the telnet server -- does not return unless an error occurs */ + +EXTERN void telnetd_init(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __NET_UIP_TELNETD_H */ diff --git a/nuttx/netutils/telnetd/shell.c b/nuttx/netutils/telnetd/shell.c index 3c68350e0..93fd11601 100644 --- a/nuttx/netutils/telnetd/shell.c +++ b/nuttx/netutils/telnetd/shell.c @@ -1,94 +1,139 @@ - /* - * Copyright (c) 2003, Adam Dunkels. - * All rights reserved. +/**************************************************************************** + * netutils/telnetd/telnetd.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This is a leverage of similar logic from uIP: + * + * Author: Adam Dunkels + * 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. + * 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 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. - */ + * 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. + ****************************************************************************/ -#include "shell.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ #include +#include "shell.h" -struct ptentry { +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define SHELL_PROMPT "uIP 1.0> " + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ptentry_s +{ char *commandstr; - void (* pfunc)(char *str); + void (* pfunc)(void *handle, char *str); }; -#define SHELL_PROMPT "uIP 1.0> " +/**************************************************************************** + * 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(register char *str, struct ptentry *t) +static void parse(void *handle, char *str, struct ptentry_s *t) { - struct ptentry *p; - for(p = t; p->commandstr != NULL; ++p) { - if(strncmp(p->commandstr, str, strlen(p->commandstr)) == 0) { - break; + struct ptentry_s *p; + + for (p = t; p->commandstr != NULL; ++p) + { + if (strncmp(p->commandstr, str, strlen(p->commandstr)) == 0) + { + break; + } } - } - p->pfunc(str); + p->pfunc(handle, str); } -static void help(char *str) +static void help(void *handle, char *str) { - shell_output("Available commands:", ""); - shell_output("stats - show network statistics", ""); - shell_output("conn - show TCP connections", ""); - shell_output("help, ? - show help", ""); - shell_output("exit - exit shell", ""); + 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(char *str) +static void unknown(void *handle, char *str) { - if(strlen(str) > 0) { - shell_output("Unknown command: ", str); - } + if (strlen(str) > 0) + { + shell_output(handle, "Unknown command: ", str); + } } -static struct ptentry parsetab[] = - {{"stats", help}, - {"conn", help}, - {"help", help}, - {"exit", shell_quit}, - {"?", help}, - - /* Default action */ - {NULL, unknown}}; +/**************************************************************************** + * Public Functions + ****************************************************************************/ -void shell_init(void) +void shell_init(void *handle) { } -void shell_start(void) +void shell_start(void *handle) { - shell_output("uIP command shell", ""); - shell_output("Type '?' and return for help", ""); - shell_prompt(SHELL_PROMPT); + shell_output(handle, "uIP command shell"); + shell_output(handle, "Type '?' and return for help"); + shell_prompt(handle, SHELL_PROMPT); } -void shell_input(char *cmd) +void shell_input(void *handle, char *cmd) { - parse(cmd, parsetab); - shell_prompt(SHELL_PROMPT); + parse(handle, cmd, g_parsetab); + shell_prompt(handle, SHELL_PROMPT); } diff --git a/nuttx/netutils/telnetd/shell.h b/nuttx/netutils/telnetd/shell.h index 8f89b2119..32325fe17 100644 --- a/nuttx/netutils/telnetd/shell.h +++ b/nuttx/netutils/telnetd/shell.h @@ -52,14 +52,14 @@ * be used to start listening for signals. */ -void shell_init(void); +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); +void shell_start(void *handle); /* Process a shell command. * @@ -70,34 +70,28 @@ void shell_start(void); * command The command to be processed. */ -void shell_input(char *command); +void shell_input(void *handle, char *command); /* Quit the shell. */ -void shell_quit(char *); - +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. - * - * str1 The first half of the string to be output. - * str2 The second half of the string to be output. */ -void shell_output(char *str1, char *str2); +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. * - * prompt The prompt to be printed. - * */ -void shell_prompt(char *prompt); +void shell_prompt(void *handle, char *prompt); #endif /* __SHELL_H__ */ diff --git a/nuttx/netutils/telnetd/telnetd.c b/nuttx/netutils/telnetd/telnetd.c index bf39826f5..64d14842d 100644 --- a/nuttx/netutils/telnetd/telnetd.c +++ b/nuttx/netutils/telnetd/telnetd.c @@ -1,43 +1,67 @@ -/* netutils/telnetd/telnetd.c +/**************************************************************************** + * netutils/telnetd/telnetd.c * - * Copyright (c) 2003, Adam Dunkels. - * All rights reserved. + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This is a leverage of similar logic from uIP: + * + * Author: Adam Dunkels + * 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. + * 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 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. - */ + * 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 #include +#include + +#include +#include #include +#include #include +#include +#include -#include -#include +#include +#include -#include "telnetd.h" #include "shell.h" +/**************************************************************************** + * Definitions + ****************************************************************************/ + #define ISO_nl 0x0a #define ISO_cr 0x0d @@ -49,302 +73,417 @@ #define STATE_DONT 5 #define STATE_CLOSE 6 -static struct telnetd_state s; - #define TELNET_IAC 255 #define TELNET_WILL 251 #define TELNET_WONT 252 #define TELNET_DO 253 #define TELNET_DONT 254 -void shell_quit(char *str) -{ - s.state = STATE_CLOSE; -} +/* Configurable settings */ -static void sendline(char *line) -{ - unsigned int i; +#ifndef CONFIG_NETUTILS_IOBUFFER_SIZE +# define CONFIG_NETUTILS_IOBUFFER_SIZE 512 +#endif - for (i = 0; i < TELNETD_CONF_NUMLINES; ++i) - { - if (s.lines[i] == NULL) - { - s.lines[i] = line; - break; - } - } - if (i == TELNETD_CONF_NUMLINES) - { - free(line); - } -} +#ifndef CONFIG_NETUTILS_CMD_SIZE +# define CONFIG_NETUTILS_CMD_SIZE 40 +#endif -void shell_prompt(char *str) -{ - char *line; - line = (char*)malloc(TELNETD_CONF_LINELEN); - if (line != NULL) - { - strncpy(line, str, TELNETD_CONF_LINELEN); - sendline(line); - } -} +/* 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. + */ -void shell_output(char *str1, char *str2) -{ - unsigned len; - char *line; +#ifndef CONFIG_NETUTILS_TELNETDSTACKSIZE +# define CONFIG_NETUTILS_TELNETDSTACKSIZE 4096 +#endif - line = (char*)malloc(TELNETD_CONF_LINELEN); - if (line != NULL) - { - len = strlen(str1); - strncpy(line, str1, TELNETD_CONF_LINELEN); - if (len < TELNETD_CONF_LINELEN) - { - strncpy(line + len, str2, TELNETD_CONF_LINELEN - len); - } - len = strlen(line); - if (len < TELNETD_CONF_LINELEN - 2) - { - line[len] = ISO_cr; - line[len+1] = ISO_nl; - line[len+2] = 0; - } - sendline(line); - } -} +/* Enabled dumping of all input/output buffers */ -void telnetd_init(void) -{ - uip_listen(HTONS(23)); - shell_init(); -} +#undef CONFIG_NETUTILS_TELNETD_DUMPBUFFER -static void acked(void) -{ - unsigned int i; +/**************************************************************************** + * Private Types + ****************************************************************************/ - while(s.numsent > 0) - { - free(s.lines[0]); - for (i = 1; i < TELNETD_CONF_NUMLINES; ++i) - { - s.lines[i - 1] = s.lines[i]; - } - s.lines[TELNETD_CONF_NUMLINES - 1] = NULL; - --s.numsent; - } -} +struct telnetd_s +{ + int tn_sockfd; + char tn_iobuffer[CONFIG_NETUTILS_IOBUFFER_SIZE]; + char tn_cmd[CONFIG_NETUTILS_CMD_SIZE]; + uint8 tn_bufndx; + uint8 tn_state; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: telnetd_dumpbuffer + * + * Description: + * Dump a buffer of data (debug only) + * + ****************************************************************************/ -static void senddata(struct uip_driver_s *dev, struct uip_conn *conn) +#ifdef CONFIG_NETUTILS_TELNETD_DUMPBUFFER +static void telnetd_dumpbuffer(const char *msg, const char *buffer, ssize_t nbytes) { - char *bufptr, *lineptr; - int buflen, linelen; - - bufptr = (char*)dev->d_appdata; - buflen = 0; - for (s.numsent = 0; - s.numsent < TELNETD_CONF_NUMLINES && s.lines[s.numsent] != NULL; - ++s.numsent) +#ifdef CONFIG_DEBUG + char line[128]; + int ch; + int i; + int j; + + dbg("%s:\n", msg); + for (i = 0; i < nbytes; i += 16) { - lineptr = s.lines[s.numsent]; - linelen = strlen(lineptr); - if (linelen > TELNETD_CONF_LINELEN) - { - linelen = TELNETD_CONF_LINELEN; - } - if (buflen + linelen < uip_mss(conn)) - { - memcpy(bufptr, lineptr, linelen); - bufptr += linelen; - buflen += linelen; - } - else + sprintf(line, "%04x: ", i); + + for ( j = 0; j < 16; j++) { - break; + if (i + j < nbytes) + { + sprintf(&line[strlen(line)], "%02x ", buffer[i+j] ); + } + else + { + strcpy(&line[strlen(line)], " "); + } } - } - uip_send(dev, dev->d_appdata, buflen); -} - -static void closed(void) -{ - unsigned int i; - for (i = 0; i < TELNETD_CONF_NUMLINES; ++i) - { - if (s.lines[i] != NULL) + for ( j = 0; j < 16; j++) { - free(s.lines[i]); + if (i + j < nbytes) + { + ch = buffer[i+j]; + sprintf(&line[strlen(line)], "%c", ch >= 0x20 && ch <= 0x7e ? ch : '.'); + } } + dbg("%s\n", line); } +#endif } +#else +# define telnetd_dumpbuffer(msg,buffer,nbytes) +#endif + +/**************************************************************************** + * Name: telnetd_putchar + * + * Description: + * Add another parsed character to the TELNET command string + * + ****************************************************************************/ -static void get_char(uint8 c) +static void telnetd_putchar(struct telnetd_s *pstate, uint8 ch) { - if (c == ISO_cr) + /* Ignore carriage returns */ + + if (ch == ISO_cr) { return; } - s.buf[(int)s.bufptr] = c; - if (s.buf[(int)s.bufptr] == ISO_nl || s.bufptr == sizeof(s.buf) - 1) + /* 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 (s.bufptr > 0) + if (pstate->tn_bufndx > 0) { - s.buf[(int)s.bufptr] = 0; + pstate->tn_cmd[pstate->tn_bufndx] = '\0'; } - shell_input(s.buf); - s.bufptr = 0; + + telnetd_dumpbuffer("TELNET CMD", pstate->tn_cmd, strlen(pstate->tn_cmd)); + shell_input(pstate, pstate->tn_cmd); + pstate->tn_bufndx = 0; } else { - ++s.bufptr; + pstate->tn_bufndx++; + vdbg("Add '%c', bufndx=%d\n", ch, pstate->tn_bufndx); } } -static void sendopt(uint8 option, uint8 value) +/**************************************************************************** + * Name: telnetd_sendopt + * + * Description: + * + ****************************************************************************/ + +static void telnetd_sendopt(struct telnetd_s *pstate, uint8 option, uint8 value) { - char *line; - line = (char*)malloc(TELNETD_CONF_LINELEN); - if (line != NULL) + uint8 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) { - line[0] = TELNET_IAC; - line[1] = option; - line[2] = value; - line[3] = 0; - sendline(line); + dbg("[%d] Failed to send TELNET_IAC\n", pstate->tn_sockfd); } } -static void newdata(struct uip_driver_s *dev) -{ - uint16 len; - uint8 c; - char *dataptr; +/**************************************************************************** + * Name: telnetd_receive + * + * Description: + * Process a received TELENET buffer + * + ****************************************************************************/ - len = uip_datalen(dev); - dataptr = (char *)dev->d_appdata; +static int telnetd_receive(struct telnetd_s *pstate, size_t len) +{ + char *ptr = pstate->tn_iobuffer; + uint8 ch; - while(len > 0 && s.bufptr < sizeof(s.buf))\ + while (len > 0) { - c = *dataptr; - ++dataptr; - --len; - switch(s.state) + ch = *ptr++; + len--; + + vdbg("ch=%02x state=%d\n", ch, pstate->tn_state); + switch (pstate->tn_state) { case STATE_IAC: - if (c == TELNET_IAC) + if (ch == TELNET_IAC) { - get_char(c); - s.state = STATE_NORMAL; + telnetd_putchar(pstate, ch); + pstate->tn_state = STATE_NORMAL; } else { - switch (c) + switch (ch) { case TELNET_WILL: - s.state = STATE_WILL; + pstate->tn_state = STATE_WILL; break; + case TELNET_WONT: - s.state = STATE_WONT; + pstate->tn_state = STATE_WONT; break; + case TELNET_DO: - s.state = STATE_DO; + pstate->tn_state = STATE_DO; break; + case TELNET_DONT: - s.state = STATE_DONT; + pstate->tn_state = STATE_DONT; break; + default: - s.state = STATE_NORMAL; + pstate->tn_state = STATE_NORMAL; break; } } break; + case STATE_WILL: /* Reply with a DONT */ - sendopt(TELNET_DONT, c); - s.state = STATE_NORMAL; + + telnetd_sendopt(pstate, TELNET_DONT, ch); + pstate->tn_state = STATE_NORMAL; break; case STATE_WONT: /* Reply with a DONT */ - sendopt(TELNET_DONT, c); - s.state = STATE_NORMAL; + + telnetd_sendopt(pstate, TELNET_DONT, ch); + pstate->tn_state = STATE_NORMAL; break; + case STATE_DO: /* Reply with a WONT */ - sendopt(TELNET_WONT, c); - s.state = STATE_NORMAL; + + telnetd_sendopt(pstate, TELNET_WONT, ch); + pstate->tn_state = STATE_NORMAL; break; + case STATE_DONT: /* Reply with a WONT */ - sendopt(TELNET_WONT, c); - s.state = STATE_NORMAL; + + telnetd_sendopt(pstate, TELNET_WONT, ch); + pstate->tn_state = STATE_NORMAL; break; + case STATE_NORMAL: - if (c == TELNET_IAC) + if (ch == TELNET_IAC) { - s.state = STATE_IAC; + pstate->tn_state = STATE_IAC; } else { - get_char(c); + telnetd_putchar(pstate, ch); } break; } } + return OK; } -/* This function is called by the UIP interrupt handling logic whenevent an - * event of interest occurs. - */ +/**************************************************************************** + * 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). + * + ****************************************************************************/ -uint8 uip_interrupt_event(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags) +static void *telnetd_handler(void *arg) { -#warning OBSOLETE -- needs to be redesigned - unsigned int i; + struct telnetd_s *pstate = (struct telnetd_s *)malloc(sizeof(struct telnetd_s)); + int sockfd = (int)arg; + int ret = ERROR; - if (uip_connected_event(flags)) + dbg("[%d] Started\n", sockfd); + + /* Verify that the state structure was successfully allocated */ + + if (pstate) { - for (i = 0; i < TELNETD_CONF_NUMLINES; ++i) - { - s.lines[i] = NULL; - } - s.bufptr = 0; - s.state = STATE_NORMAL; - - shell_start(); - } - if (s.state == STATE_CLOSE) - { - s.state = STATE_NORMAL; - return UIP_CLOSE; - } + /* Initialize the thread state structure */ - if (uip_close_event(flags) || uip_abort_event(flags) || uip_timeout_event(flags)) - { - closed(); - } + memset(pstate, 0, sizeof(struct telnetd_s)); + pstate->tn_sockfd = sockfd; + pstate->tn_state = STATE_NORMAL; - if (uip_ack_event(flags)) - { - acked(); - } + /* Start up the shell */ - if (uip_newdata_event(flags)) - { - newdata(dev); - } + shell_init(pstate); + shell_start(pstate); - if (uip_rexmit_event(flags) || uip_newdata_event(flags) || uip_ack_event(flags) || - uip_connected_event(flags) || uip_poll_event(flags)) - { - senddata(dev, conn); - } + /* 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); - return flags; + /* End of command processing -- Clean up and exit */ + + free(pstate); + } + + /* Exit the task */ + + dbg("[%d] Exitting\n", sockfd); + close(sockfd); + pthread_exit(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 prompt\n", pstate->tn_sockfd); + } +} + +/**************************************************************************** + * Name: shell_quit + * + * Description: + * Quit the shell + * + ****************************************************************************/ + +void shell_quit(void *handle, char *str) +{ + struct telnetd_s *pstate = (struct telnetd_s *)handle; + pstate->tn_state = STATE_CLOSE; +} + diff --git a/nuttx/netutils/telnetd/telnetd.h b/nuttx/netutils/telnetd/telnetd.h deleted file mode 100644 index 4eef0b726..000000000 --- a/nuttx/netutils/telnetd/telnetd.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ - -#ifndef __TELNETD_H__ -#define __TELNETD_H__ - -#include -#include - -#ifndef TELNETD_CONF_LINELEN -#define TELNETD_CONF_LINELEN 40 -#endif -#ifndef TELNETD_CONF_NUMLINES -#define TELNETD_CONF_NUMLINES 16 -#endif - -struct telnetd_state -{ - char *lines[TELNETD_CONF_NUMLINES]; - char buf[TELNETD_CONF_LINELEN]; - char bufptr; - uint8 numsent; - uint8 state; -}; - -#endif /* __TELNETD_H__ */ diff --git a/nuttx/netutils/webserver/httpd.c b/nuttx/netutils/webserver/httpd.c index 08ec2a295..755d11892 100644 --- a/nuttx/netutils/webserver/httpd.c +++ b/nuttx/netutils/webserver/httpd.c @@ -1,5 +1,5 @@ /**************************************************************************** - * httpd + * netutils/webserver/httpd.c * httpd Web server * * Copyright (C) 2007 Gregory Nutt. All rights reserved. @@ -510,7 +510,7 @@ int httpd_listen(void) { /* Execute httpd_handler on each connection to port 80 */ - uip_server(HTONS(80), httpd_handler, CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE); + uip_server(HTONS(80), httpd_handler, CONFIG_NETUTILS_HTTPDSTACKSIZE); /* uip_server only returns on errors */ diff --git a/nuttx/netutils/webserver/httpd.h b/nuttx/netutils/webserver/httpd.h index 7e70ccd41..9b5ba58d5 100644 --- a/nuttx/netutils/webserver/httpd.h +++ b/nuttx/netutils/webserver/httpd.h @@ -70,8 +70,8 @@ * for the thread. Use a default if the user provided no stacksize. */ -#ifndef CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE -# define CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE 4096 +#ifndef CONFIG_NETUTILS_HTTPDSTACKSIZE +# define CONFIG_NETUTILS_HTTPDSTACKSIZE 4096 #endif /**************************************************************************** -- cgit v1.2.3