diff --git a/COPYRIGHT b/COPYRIGHT deleted file mode 100644 index 5cab33c..0000000 --- a/COPYRIGHT +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. 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. - * - * This file is part of the uIP TCP/IP stack. - * - * $Id: COPYRIGHT,v 1.3 2002/01/15 18:08:43 adam Exp $ - * - */ diff --git a/README b/README index 3891938..0cbcb2f 100644 --- a/README +++ b/README @@ -1,12 +1,11 @@ uIP is a very small implementation of the TCP/IP stack that is written by Adam Dunkels . More information can be obtained -at the uIP homepage at . - -This is version $Name: uip-0-6 $. +at the uIP homepage at + http://dunkels.com/adam/uip/ The directory structure look as follows: -apps/ - contains some sample applications -cc65/ - uIP for the 6502 CPU -uip/ - actual uIP TCP/IP and ARP code -unix - uIP as a user space process under FreeBSD or Linux +apps/ - example applications +doc/ - documentation +uip/ - actual uIP TCP/IP, SLIP and ARP code +unix/ - Example of how to run uIP as a user space process under FreeBSD or Linux diff --git a/apps/httpd/cgi.c b/apps/httpd/cgi.c index 82c46a5..adb53e9 100644 --- a/apps/httpd/cgi.c +++ b/apps/httpd/cgi.c @@ -1,3 +1,22 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * HTTP server script language C functions file. + * \author Adam Dunkels + * + * This file contains functions that are called by the web server + * scripts. The functions takes one argument, and the return value is + * interpreted as follows. A zero means that the function did not + * complete and should be invoked for the next packet as well. A + * non-zero value indicates that the function has completed and that + * the web server should move along to the next script line. + * + */ + /* * Copyright (c) 2001, Adam Dunkels. * All rights reserved. @@ -10,10 +29,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,17 +47,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: cgi.c,v 1.21 2002/01/13 21:12:40 adam Exp $ - * - */ - -/* - * This file includes functions that are called by the web server - * scripts. The functions takes no argument, and the return value is - * interpreted as follows. A zero means that the function did not - * complete and should be invoked for the next packet as well. A - * non-zero value indicates that the function has completed and that - * the web server should move along to the next script line. + * $Id: cgi.c,v 1.23.2.4 2003/10/07 13:22:27 adam Exp $ * */ @@ -53,9 +59,9 @@ #include #include -static u8_t print_stats(void); -static u8_t file_stats(void); -static u8_t tcp_stats(void); +static u8_t print_stats(u8_t next); +static u8_t file_stats(u8_t next); +static u8_t tcp_stats(u8_t next); cgifunction cgitab[] = { print_stats, /* CGI function "a" */ @@ -110,14 +116,14 @@ static const char *states[] = { * packet. */ static u8_t -print_stats(void) +print_stats(u8_t next) { #if UIP_STATISTICS u16_t i, j; u8_t *buf; u16_t *databytes; - if(uip_acked()) { + if(next) { /* If our last data has been acknowledged, we move on the next chunk of statistics. */ hs->count = hs->count + 4; @@ -151,12 +157,12 @@ print_stats(void) } /*-----------------------------------------------------------------------------------*/ static u8_t -file_stats(void) +file_stats(u8_t next) { /* We use sprintf() to print the number of file accesses to a particular file (given as an argument to the function in the script). We then use uip_send() to actually send the data. */ - if(uip_acked()) { + if(next) { return 1; } uip_send(uip_appdata, sprintf((char *)uip_appdata, "%5u", fs_count(&hs->script[4]))); @@ -164,11 +170,11 @@ file_stats(void) } /*-----------------------------------------------------------------------------------*/ static u8_t -tcp_stats(void) +tcp_stats(u8_t next) { struct uip_conn *conn; - if(uip_acked()) { + if(next) { /* If the previously sent data has been acknowledged, we move forward one connection. */ if(++hs->count == UIP_CONNS) { @@ -181,24 +187,24 @@ tcp_stats(void) conn = &uip_conns[hs->count]; if((conn->tcpstateflags & TS_MASK) == CLOSED) { uip_send(uip_appdata, sprintf((char *)uip_appdata, - "--%d%d%c %c\r\n", + "--%u%u%c %c\r\n", conn->nrtx, conn->timer, - (conn->tcpstateflags & UIP_OUTSTANDING)? '*':' ', - (conn->tcpstateflags & UIP_STOPPED)? '!':' ')); + (uip_outstanding(conn))? '*':' ', + (uip_stopped(conn))? '!':' ')); } else { uip_send(uip_appdata, sprintf((char *)uip_appdata, - "%d.%d.%d.%d:%d%s%d%d%c %c\r\n", - ntohs(conn->ripaddr[0]) >> 8, - ntohs(conn->ripaddr[0]) & 0xff, - ntohs(conn->ripaddr[1]) >> 8, - ntohs(conn->ripaddr[1]) & 0xff, - ntohs(conn->rport), + "%u.%u.%u.%u:%u%s%u%u%c %c\r\n", + htons(conn->ripaddr[0]) >> 8, + htons(conn->ripaddr[0]) & 0xff, + htons(conn->ripaddr[1]) >> 8, + htons(conn->ripaddr[1]) & 0xff, + htons(conn->rport), states[conn->tcpstateflags & TS_MASK], conn->nrtx, conn->timer, - (conn->tcpstateflags & UIP_OUTSTANDING)? '*':' ', - (conn->tcpstateflags & UIP_STOPPED)? '!':' ')); + (uip_outstanding(conn))? '*':' ', + (uip_stopped(conn))? '!':' ')); } return 0; } diff --git a/apps/httpd/cgi.h b/apps/httpd/cgi.h index ccac8a0..dbc98f7 100644 --- a/apps/httpd/cgi.h +++ b/apps/httpd/cgi.h @@ -1,3 +1,14 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * HTTP script language header file. + * \author Adam Dunkels + */ + /* * Copyright (c) 2001, Adam Dunkels. * All rights reserved. @@ -10,10 +21,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,15 +39,19 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: cgi.h,v 1.3 2002/01/10 19:18:12 adam Exp $ + * $Id: cgi.h,v 1.3.2.4 2003/10/07 13:22:27 adam Exp $ * */ #ifndef __CGI_H__ #define __CGI_H__ -typedef u8_t (* cgifunction)(void); +typedef u8_t (* cgifunction)(u8_t next); +/** + * A table containing pointers to C functions that can be called from + * a web server script. + */ extern cgifunction cgitab[]; #endif /* __CGI_H__ */ diff --git a/apps/httpd/fs.c b/apps/httpd/fs.c index 26bc0a5..6b18545 100644 --- a/apps/httpd/fs.c +++ b/apps/httpd/fs.c @@ -1,3 +1,16 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * HTTP server read-only file system code. + * \author Adam Dunkels + * + * A simple read-only filesystem. + */ + /* * Copyright (c) 2001, Swedish Institute of Computer Science. * All rights reserved. @@ -10,11 +23,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Swedish Institute - * of Computer Science and its contributors. - * 4. Neither the name of the Institute nor the names of its contributors + * 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. * @@ -34,10 +43,11 @@ * * Author: Adam Dunkels * - * $Id: fs.c,v 1.6 2001/11/25 18:47:36 adam Exp $ + * $Id: fs.c,v 1.7.2.3 2003/10/07 13:22:27 adam Exp $ */ #include "uip.h" +#include "httpd.h" #include "fs.h" #include "fsdata.h" diff --git a/apps/httpd/fs.h b/apps/httpd/fs.h index 88ac2d9..2d9693b 100644 --- a/apps/httpd/fs.h +++ b/apps/httpd/fs.h @@ -1,3 +1,14 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * HTTP server read-only file system header file. + * \author Adam Dunkels + */ + /* * Copyright (c) 2001, Swedish Institute of Computer Science. * All rights reserved. @@ -10,11 +21,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Swedish Institute - * of Computer Science and its contributors. - * 4. Neither the name of the Institute nor the names of its contributors + * 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. * @@ -34,20 +41,29 @@ * * Author: Adam Dunkels * - * $Id: fs.h,v 1.6 2001/11/25 18:47:36 adam Exp $ + * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ */ #ifndef __FS_H__ #define __FS_H__ #include "uip.h" +/** + * An open file in the read-only file system. + */ struct fs_file { - char *data; - int len; + char *data; /**< The actual file data. */ + int len; /**< The length of the file data. */ }; -/* file must be allocated by caller and will be filled in - by the function. */ +/** + * Open a file in the read-only file system. + * + * \param name The name of the file. + * + * \param file The file pointer, which must be allocated by caller and + * will be filled in by the function. + */ int fs_open(const char *name, struct fs_file *file); #ifdef FS_STATISTICS @@ -56,6 +72,9 @@ u16_t fs_count(char *name); #endif /* FS_STATISTICS */ #endif /* FS_STATISTICS */ +/** + * Initialize the read-only file system. + */ void fs_init(void); #endif /* __FS_H__ */ diff --git a/apps/httpd/fs/404.html b/apps/httpd/fs/404.html new file mode 100644 index 0000000..8d6beec --- /dev/null +++ b/apps/httpd/fs/404.html @@ -0,0 +1 @@ +

404 - file not found

\ No newline at end of file diff --git a/apps/httpd/fs/about.html b/apps/httpd/fs/about.html new file mode 100644 index 0000000..0d0dd6f --- /dev/null +++ b/apps/httpd/fs/about.html @@ -0,0 +1,18 @@ + + +
+
+

Welcome

+

+These web pages are served by the small web server running on top of +the uIP TCP/IP +stack. +

+

+Click on the links above to see some status information about the web +server and the TCP/IP stack. +

+
+
+ + \ No newline at end of file diff --git a/apps/httpd/fs/cgi/files b/apps/httpd/fs/cgi/files index e07e86d..b9d929b 100644 --- a/apps/httpd/fs/cgi/files +++ b/apps/httpd/fs/cgi/files @@ -7,14 +7,19 @@ i /files_header.html # the access statistics of that file. t /index.html c b /index.html -t -t /cgi/files +t /about.html +c b /about.html +t /control.html +c b /control.html +t /img/bg.png +c b /img/bg.png +t /404.html +c b /404.html +t /cgi/files c b /cgi/files -t -t /cgi/stats +t /cgi/stats c b /cgi/stats -t -t /cgi/tcp +t /cgi/tcp c b /cgi/tcp t # Include the HTML footer. diff --git a/apps/httpd/fs/control.html b/apps/httpd/fs/control.html new file mode 100644 index 0000000..2327497 --- /dev/null +++ b/apps/httpd/fs/control.html @@ -0,0 +1,14 @@ + + +
+
+

uIP web server test pages

+[ About | +Connections | +Files | +Statistics ] +
+
+ + \ No newline at end of file diff --git a/apps/httpd/fs/files_footer.plain b/apps/httpd/fs/files_footer.plain index b3bd3ed..8e7b84f 100644 --- a/apps/httpd/fs/files_footer.plain +++ b/apps/httpd/fs/files_footer.plain @@ -1,30 +1,3 @@ - - - - -

- -$Date: 2001/11/24 15:43:36 $ - -

- - - - - -  - - - - - - - -
-
-© -Copyright Adam Dunkels 2001
- + diff --git a/apps/httpd/fs/files_header.html b/apps/httpd/fs/files_header.html index 33aba5f..9e3ef68 100644 --- a/apps/httpd/fs/files_header.html +++ b/apps/httpd/fs/files_header.html @@ -1,15 +1,4 @@ -uIP web server page hits - - - - - - -
-
uIP web server page hits
-
 
-
- +
diff --git a/apps/httpd/fs/img/bg.png b/apps/httpd/fs/img/bg.png new file mode 100644 index 0000000..18533b3 Binary files /dev/null and b/apps/httpd/fs/img/bg.png differ diff --git a/apps/httpd/fs/index.html b/apps/httpd/fs/index.html index 40ff844..a8aa4d8 100644 --- a/apps/httpd/fs/index.html +++ b/apps/httpd/fs/index.html @@ -1,65 +1,14 @@ uIP web server test page - -
- - - - - - -
-
uIP web server test page
-
 
-
- -

-This is a simple test page for the HTTP server running on top of the -uIP TCP/IP stack. This page is served by the small web server. -

- -

-The web server also supports a few virtual pages:
-

  • -/cgi/files which shows individual page -hits.
    - -
  • -/cgi/tcp which shows current TCP connection -states.
    - -
  • -/cgi/stats which shows uIP TCP/IP -statistics.
    -

    - -

    -For more information, see the uIP home page. -

    - -

    - -$Date: 2001/11/24 15:43:36 $ - -

    - - -
  • - -
     
    - - - - - - -
    -
    -© -Copyright Adam Dunkels 2001
    + + + + + +<body> +Your browser must support frames </body> -</html> + + \ No newline at end of file diff --git a/apps/httpd/fs/stats_footer.plain b/apps/httpd/fs/stats_footer.plain index 40a4bab..8e7b84f 100644 --- a/apps/httpd/fs/stats_footer.plain +++ b/apps/httpd/fs/stats_footer.plain @@ -1,29 +1,3 @@
    - - -

    - -$Date: 2001/11/24 15:43:36 $ - -

    - - -
    - - -  - - - - - - - -
    -
    -© -Copyright Adam Dunkels 2001
    - diff --git a/apps/httpd/fs/stats_header.html b/apps/httpd/fs/stats_header.html index 4dc088c..e2e07ba 100644 --- a/apps/httpd/fs/stats_header.html +++ b/apps/httpd/fs/stats_header.html @@ -1,19 +1,8 @@ -uIP TCP/IP statistics - - - - - - - - -
    -
    uIP TCP/IP statistics
    -
     
    -
    -
    -
    + +
     IP           Packets dropped
                  Packets received
    @@ -38,4 +27,4 @@ TCP          Packets dropped
     	     No connection avaliable
     	     Connection attempts to closed ports
     
    -
    +
    \ No newline at end of file
    diff --git a/apps/httpd/fs/tcp_footer.plain b/apps/httpd/fs/tcp_footer.plain
    index 898a866..9be88c0 100644
    --- a/apps/httpd/fs/tcp_footer.plain
    +++ b/apps/httpd/fs/tcp_footer.plain
    @@ -1,31 +1,5 @@
     
    -
    +
    - - -

    - -$Date: 2001/11/24 15:43:36 $ - -

    - - -
    - -
     
    - - - - - - -
    -
    -© -Copyright Adam Dunkels 2001
    - - + \ No newline at end of file diff --git a/apps/httpd/fs/tcp_header.html b/apps/httpd/fs/tcp_header.html index 5694410..595e99c 100644 --- a/apps/httpd/fs/tcp_header.html +++ b/apps/httpd/fs/tcp_header.html @@ -1,19 +1,6 @@ -uIP TCP connection states - - - - - - -
    -
    uIP TCP connection states
    -
     
    -
    -
    - - +
    diff --git a/apps/httpd/fsdata.c b/apps/httpd/fsdata.c index a9c4277..3c41ef3 100644 --- a/apps/httpd/fsdata.c +++ b/apps/httpd/fsdata.c @@ -1,12 +1,3 @@ -static const char data_cgi_stats[] = { - /* /cgi/stats */ - 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0, - 0x69, 0x20, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, - 0xa, 0x63, 0x20, 0x61, 0xa, 0x69, 0x20, 0x2f, 0x73, 0x74, - 0x61, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, - 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xa, 0x2e, 0xa, }; - static const char data_cgi_files[] = { /* /cgi/files */ 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0, @@ -43,24 +34,57 @@ static const char data_cgi_files[] = { 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x63, 0x20, 0x62, 0x20, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x74, 0x20, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, - 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x74, 0x20, 0x3c, 0x74, 0x72, - 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, - 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x22, 0x3e, 0x2f, 0x63, 0x67, 0x69, - 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x3c, 0x2f, 0x61, 0x3e, + 0x2f, 0x74, 0x72, 0x3e, 0x20, 0x3c, 0x74, 0x72, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, + 0x3d, 0x22, 0x2f, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x2e, 0x68, + 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x61, 0x62, 0x6f, 0x75, + 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, - 0x63, 0x20, 0x62, 0x20, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0xa, 0x74, 0x20, 0x3c, 0x2f, 0x74, - 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x74, 0x20, - 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, - 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, 0x67, - 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x3e, 0x2f, - 0x63, 0x67, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x3c, - 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, - 0x64, 0x3e, 0xa, 0x63, 0x20, 0x62, 0x20, 0x2f, 0x63, 0x67, - 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0xa, 0x74, 0x20, + 0x63, 0x20, 0x62, 0x20, 0x2f, 0x61, 0x62, 0x6f, 0x75, 0x74, + 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x74, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x20, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x63, 0x20, + 0x62, 0x20, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x74, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x20, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x69, 0x6d, 0x67, + 0x2f, 0x62, 0x67, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x3e, 0x2f, + 0x69, 0x6d, 0x67, 0x2f, 0x62, 0x67, 0x2e, 0x70, 0x6e, 0x67, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0xa, 0x63, 0x20, 0x62, 0x20, 0x2f, 0x69, + 0x6d, 0x67, 0x2f, 0x62, 0x67, 0x2e, 0x70, 0x6e, 0x67, 0xa, + 0x74, 0x20, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, + 0x72, 0x3e, 0x20, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, + 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, + 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0xa, 0x63, 0x20, 0x62, 0x20, 0x2f, 0x34, + 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x74, 0x20, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, - 0xa, 0x74, 0x20, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, + 0x20, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, + 0x67, 0x69, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x3e, + 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0xa, 0x63, 0x20, 0x62, 0x20, 0x2f, 0x63, + 0x67, 0x69, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0xa, 0x74, + 0x20, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, + 0x3e, 0x20, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, + 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, + 0x63, 0x67, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, + 0x3e, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, + 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, + 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x63, 0x20, 0x62, 0x20, 0x2f, + 0x63, 0x67, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0xa, + 0x74, 0x20, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, + 0x72, 0x3e, 0x20, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x74, 0x63, 0x70, 0x22, 0x3e, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x74, 0x63, 0x70, 0x3c, 0x2f, @@ -76,6 +100,15 @@ static const char data_cgi_files[] = { 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2e, 0xa, 0x2e, }; +static const char data_cgi_stats[] = { + /* /cgi/stats */ + 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0, + 0x69, 0x20, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, + 0xa, 0x63, 0x20, 0x61, 0xa, 0x69, 0x20, 0x2f, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, + 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xa, 0x2e, 0xa, }; + static const char data_cgi_tcp[] = { /* /cgi/tcp */ 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x74, 0x63, 0x70, 0, @@ -85,13 +118,303 @@ static const char data_cgi_tcp[] = { 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xa, 0x2e, }; +static const char data_img_bg_png[] = { + /* /img/bg.png */ + 0x2f, 0x69, 0x6d, 0x67, 0x2f, 0x62, 0x67, 0x2e, 0x70, 0x6e, 0x67, 0, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, + 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, + 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, + 0xd, 0xa, 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, + 00, 00, 00, 0xd, 0x49, 0x48, 0x44, 0x52, 00, 00, + 0x3, 0x1d, 00, 00, 00, 0x5e, 0x8, 0x6, 00, 00, + 00, 0x46, 0xbd, 0x79, 0xcc, 00, 00, 00, 0x6, 0x62, + 0x4b, 0x47, 0x44, 00, 0xff, 00, 0xff, 00, 0xff, 0xa0, + 0xbd, 0xa7, 0x93, 00, 00, 00, 0x9, 0x70, 0x48, 0x59, + 0x73, 00, 00, 0xb, 0x12, 00, 00, 0xb, 0x12, 0x1, + 0xd2, 0xdd, 0x7e, 0xfc, 00, 00, 00, 0x7, 0x74, 0x49, + 0x4d, 0x45, 0x7, 0xd3, 0xa, 0x5, 0x12, 0x22, 0x33, 0x22, + 0xd0, 0x7c, 0x9a, 00, 00, 00, 0x1d, 0x74, 0x45, 0x58, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 00, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, + 0xef, 0x64, 0x25, 0x6e, 00, 00, 0x3, 0xa0, 0x49, 0x44, + 0x41, 0x54, 0x78, 0xda, 0xed, 0xdd, 0xc1, 0x76, 0x9a, 0x40, + 0x18, 0x80, 0x51, 0x27, 0xc7, 0x5, 0x6c, 0xd1, 0x65, 0x1a, + 0xec, 0xe9, 0xfb, 0xbf, 0x45, 0x9e, 0x23, 0xd5, 0xb4, 0x4b, + 0x71, 0x19, 0xdd, 0x4d, 0x97, 0x36, 0x8a, 0x6, 0x1c, 0x82, + 0x20, 0xf7, 0xee, 0x92, 0xa8, 0x3f, 0xc, 0x68, 0xfa, 0xa1, + 0x3d, 0x9, 0x6f, 0xaf, 0x1f, 0x71, 0x76, 0x26, 0xcc, 0x6e, + 0x15, 0x9e, 0xce, 0xbf, 0x17, 0xe3, 0x71, 0x44, 0xb8, 0xfd, + 0xa1, 0x93, 0xd5, 0x6d, 0x5b, 0x7f, 0xc3, 0x13, 0xef, 0x1e, + 0x86, 0xb3, 0x2d, 0x5d, 0x6d, 0xdb, 0xf2, 0x57, 0x96, 0x34, + 0x77, 0xfb, 0xfb, 0x90, 0x74, 0xff, 0xe5, 0xcf, 0xb4, 0xf9, + 0xbb, 0x4d, 0xda, 0xfc, 0xa2, 0xcc, 0x92, 0xd6, 0xb4, 0x5a, + 0x5f, 0x99, 0xdf, 0xe0, 0x5c, 0x5f, 0xae, 0xb2, 0xd9, 0x20, + 0x85, 0x6f, 0x5c, 0xff, 0x70, 0x7c, 0x2d, 0x5a, 0x94, 0xf9, + 0xf0, 0x76, 0xfd, 0x69, 0x36, 0x39, 0x53, 0xdc, 0xe7, 0x41, + 0xfc, 0x1e, 0x18, 0xe1, 0xef, 0x41, 0xc6, 0xf1, 0x7c, 0xa9, + 0x3d, 0x4f, 0xe3, 0x83, 0x1f, 0xfc, 0xb1, 0x1e, 0x17, 0xcb, + 0x4, 00, 00, 0x68, 0x33, 00, 00, 00, 0xd1, 0x1, + 00, 00, 0x88, 0xe, 00, 00, 0x40, 0x74, 00, 00, + 00, 0x88, 0xe, 00, 00, 0x40, 0x74, 00, 00, 00, + 0xa2, 0x3, 00, 00, 0x40, 0x74, 00, 00, 00, 0xa2, + 0x3, 00, 00, 0x40, 0x74, 00, 00, 00, 0xa2, 0x3, + 00, 00, 0x10, 0x1d, 00, 0x1d, 0xa, 0x96, 00, 00, + 0x44, 0x7, 00, 00, 0x40, 0x4b, 0xe1, 0xed, 0xf5, 0x23, + 0xd6, 0x7c, 0xfb, 0xf6, 0x7, 0xac, 0xc9, 0x98, 0x18, 0x8f, + 0x23, 0xc2, 0x1d, 0xaf, 0x64, 0x86, 0x7b, 0x26, 0x56, 0xe2, + 0x7e, 0x77, 0xba, 0x6e, 0x1d, 0x1f, 0x83, 0xa4, 0x6d, 0xb, + 0xfd, 0x6e, 0x6b, 0x97, 0x6b, 0x1a, 0xee, 0x7c, 0x55, 0x7e, + 0xb1, 0xca, 0x92, 0x9e, 0xb, 0xdb, 0xf5, 0x21, 0x69, 0xfe, + 0x32, 0x61, 0xfe, 0x18, 0x8f, 0xf7, 0xc3, 0xbf, 0x46, 0xd9, + 0xe7, 0xe1, 0xaf, 0xd5, 0xd8, 0xdf, 0x9, 0xf4, 0x4e, 0xe6, + 0x24, 0x9e, 0x2f, 0xb5, 0xe7, 0x69, 0x7c, 0xf0, 0x83, 0x3f, + 0xd6, 0xe3, 0x62, 0x99, 00, 00, 00, 0x6d, 0x6, 00, + 00, 0x20, 0x3a, 00, 00, 00, 0xd1, 0x1, 00, 00, + 0x88, 0xe, 00, 00, 00, 0xd1, 0x1, 00, 00, 0x88, + 0xe, 00, 00, 0x40, 0x74, 00, 00, 00, 0x88, 0xe, + 00, 00, 0x40, 0x74, 00, 00, 00, 0x88, 0xe, 0x98, + 0xaa, 0xe0, 0x59, 0xf, 00, 0x88, 0xe, 00, 0x86, 0x53, + 0xa9, 0x96, 00, 00, 0xd1, 0x1, 00, 00, 0x88, 0xe, + 00, 00, 0x40, 0x74, 00, 00, 00, 0x7c, 0x93, 0xb9, + 0x25, 0x80, 0xfb, 0x28, 0xca, 0xec, 0xe2, 0xcf, 0x42, 0x83, + 0xcf, 0xd1, 0x57, 0xeb, 0xc3, 0xe5, 0x1f, 0x36, 0xb8, 0x9c, + 0xb0, 0x5c, 0x65, 0x49, 0xdb, 0xbf, 0xbd, 0x30, 0x3f, 0x34, + 0xfc, 0x3f, 00, 0x8b, 0x32, 0x6d, 0xfe, 0x6e, 0x73, 0x68, + 0x7f, 0xa7, 0x10, 0xff, 0x9b, 0x9f, 0x27, 0xcd, 0xaf, 0xde, + 0xf7, 0xed, 0x46, 0x9f, 0x1c, 0x93, 0xe2, 0x39, 0xf7, 0x24, + 00, 0x60, 0x32, 0xbc, 0xd3, 0x1, 00, 00, 0x88, 0xe, + 00, 00, 0x40, 0x74, 00, 00, 00, 0x88, 0xe, 00, + 00, 0x40, 0x74, 00, 00, 00, 0x8f, 0x1f, 0x1d, 0xdd, + 0xfe, 0xf9, 0xd9, 0x18, 0xa3, 0x55, 0x6, 00, 00, 0xd1, + 0xc1, 0x64, 0x84, 0x8e, 0x1f, 0x2e, 0x58, 0x52, 00, 00, + 0x44, 0x7, 00, 00, 0x20, 0x3a, 00, 00, 00, 0xd1, + 0x1, 00, 00, 0x20, 0x3a, 00, 00, 00, 0xd1, 0x1, + 00, 00, 0x88, 0xe, 00, 00, 00, 0xd1, 0x1, 00, + 00, 0x88, 0xe, 00, 00, 0x80, 0xb9, 0x25, 0x80, 0xfb, + 0xd8, 0x6d, 0xe, 0x77, 0x9d, 0xbf, 0x5d, 0xa7, 0xcd, 0x5f, + 0xae, 0xb2, 0xa4, 0xfb, 0x57, 0x35, 0xfb, 0xdf, 0xe6, 0x8f, + 0x4d, 0x16, 0x65, 0xbb, 0xf9, 0xa7, 0x8f, 0x5d, 0x6d, 0xf6, + 0xe7, 0x37, 0x88, 0xf1, 0xca, 0x3, 0x7c, 0xfe, 0x72, 0xf1, + 0x92, 0x3b, 0x89, 0x1, 0xa0, 0x21, 0xef, 0x74, 00, 00, + 00, 0xa2, 0x3, 00, 00, 0x10, 0x1d, 00, 00, 00, + 0xa2, 0x63, 0xac, 0xda, 0x7c, 0xce, 0x1d, 00, 00, 0x44, + 0x7, 0xe0, 0x59, 0xd, 00, 0xf8, 0xe7, 0x9, 00, 00, + 0x80, 0xe8, 00, 00, 00, 0x44, 0x7, 00, 00, 0x80, + 0xe8, 00, 00, 00, 0x44, 0x7, 00, 00, 0x20, 0x3a, + 00, 00, 00, 0x44, 0x7, 00, 00, 0x20, 0x3a, 00, + 00, 00, 0xd1, 0x1, 00, 00, 0x20, 0x3a, 00, 00, + 0x80, 0x81, 0x98, 0x5b, 0x2, 0xe0, 0x16, 0xdb, 0xf5, 0xa1, + 0xf6, 0xfb, 0x21, 0xf4, 0x33, 0x7f, 0xb7, 0x39, 0xb4, 0xbb, + 0x43, 0x88, 0x9f, 0xbe, 0x5c, 0x94, 0x79, 0xd2, 0xfc, 0xea, + 0x7d, 0xdf, 0x6e, 0xfc, 0xc9, 0x25, 0x9e, 0xe2, 0xb9, 0xbf, + 0xf9, 0x75, 0xc7, 0xa4, 0xf8, 0x91, 0x3b, 0x89, 0x1, 0xe8, + 0x8d, 0x77, 0x3a, 00, 00, 00, 0xd1, 0x1, 0x43, 0xd3, + 0xd7, 0xd5, 0x7c, 0xeb, 0x2, 00, 0x88, 0xe, 00, 0xbe, + 0x8e, 0x31, 0xaf, 0xb4, 00, 0x88, 0xe, 00, 00, 00, + 0xd1, 0x1, 00, 00, 0x88, 0xe, 00, 00, 00, 0xd1, + 0x1, 00, 00, 0x88, 0xe, 00, 00, 0x40, 0x74, 00, + 00, 00, 0x88, 0xe, 00, 00, 0x40, 0x74, 00, 00, + 00, 0xa2, 0x3, 00, 00, 0x60, 0x34, 0xd1, 0x11, 0x82, + 0x5, 0x7, 00, 00, 0xd1, 0x1, 0x43, 0x21, 0x52, 0x1, + 00, 0x44, 0x7, 00, 00, 0xc0, 0x57, 0xe6, 0x96, 00, + 0x18, 0xa3, 0xa2, 0xcc, 0x5a, 0xdd, 0xfe, 0xf4, 0xe3, 0x9d, + 0xd5, 0x66, 0x7f, 0x7e, 0x83, 0x18, 0xaf, 0x3c, 0x40, 0xb7, + 0xdb, 0xbf, 0xfb, 0xbb, 0x4f, 0xba, 0xff, 0xe2, 0x25, 0x4f, + 0x9b, 0xff, 0xa7, 0xe1, 0xfc, 0xb, 0xfb, 0x5d, 0x3c, 0xe7, + 0xdf, 0xbe, 0xff, 0xe1, 0xca, 0x65, 0xb1, 0x3e, 0xe6, 0x5f, + 0x3d, 0xff, 0x12, 0xe7, 0x3, 0x4c, 0x8d, 0x77, 0x3a, 00, + 00, 00, 0xd1, 0x1, 00, 00, 0x88, 0xe, 00, 00, + 00, 0xd1, 0x1, 00, 00, 0x88, 0xe, 00, 00, 0x40, + 0x74, 00, 00, 00, 0x88, 0xe, 00, 00, 0x40, 0x74, + 00, 00, 00, 0xa2, 0x3, 00, 00, 0x40, 0x74, 0x34, + 0x13, 0xe4, 0x15, 00, 00, 0x88, 0xe, 00, 00, 0x40, + 0x74, 00, 00, 00, 0x88, 0xe, 00, 00, 0x40, 0x74, + 00, 00, 00, 0x13, 0xf1, 0xf, 0x24, 0xa1, 0x5c, 0xab, + 0x41, 0xd8, 0x92, 0xa4, 00, 00, 00, 00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; + +static const char data_about_html[] = { + /* /about.html */ + 0x2f, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, + 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, + 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, + 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x30, 0x30, 0x22, 0x20, + 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, + 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, + 0x3c, 0x68, 0x32, 0x3e, 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, + 0x65, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0xa, 0x3c, 0x70, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, + 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x54, 0x68, 0x65, + 0x73, 0x65, 0x20, 0x77, 0x65, 0x62, 0x20, 0x70, 0x61, 0x67, + 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x77, 0x65, 0x62, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x72, 0x75, + 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x70, 0x20, 0x6f, 0x66, 0xa, 0x74, 0x68, 0x65, 0x20, + 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, + 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, + 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, + 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x22, 0x20, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x3d, 0x22, 0x5f, 0x74, 0x6f, + 0x70, 0x22, 0x3e, 0x75, 0x49, 0x50, 0x20, 0x54, 0x43, 0x50, + 0x2f, 0x49, 0x50, 0xa, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x3c, + 0x2f, 0x61, 0x3e, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, + 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, + 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, + 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x20, 0x6f, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x20, 0x61, + 0x62, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, + 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x75, + 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x62, 0xa, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, + 0x50, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0xa, 0x3c, + 0x2f, 0x70, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, + 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, + 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, }; + +static const char data_control_html[] = { + /* /control.html */ + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, + 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, + 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, + 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x3d, 0x22, 0x37, 0x39, 0x37, 0x22, 0x20, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x22, 0x39, 0x34, + 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, + 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, + 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x9, + 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, + 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x62, 0x61, 0x63, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3d, 0x22, 0x2f, 0x69, + 0x6d, 0x67, 0x2f, 0x62, 0x67, 0x2e, 0x70, 0x6e, 0x67, 0x22, + 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x31, 0x3e, 0x75, + 0x49, 0x50, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x70, + 0x61, 0x67, 0x65, 0x73, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, + 0x5b, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, + 0x22, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x2e, 0x68, 0x74, 0x6d, + 0x6c, 0x22, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3d, + 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x3e, 0x41, 0x62, 0x6f, + 0x75, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x7c, 0xa, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, + 0x67, 0x69, 0x2f, 0x74, 0x63, 0x70, 0x22, 0x20, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6e, + 0x22, 0x3e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x7c, 0xa, + 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, + 0x63, 0x67, 0x69, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, + 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3d, 0x22, 0x6d, + 0x61, 0x69, 0x6e, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x7c, 0xa, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, 0x67, 0x69, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x20, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6e, + 0x22, 0x3e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, + 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x5d, 0xa, 0x3c, + 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, + 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, + 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f, + 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, + 0x6d, 0x6c, 0x3e, }; + +static const char data_404_html[] = { + /* /404.html */ + 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, + 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, + 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, + 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, + 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, + 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, + 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, + 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, + 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, + 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, + 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f, + 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, + 0x6c, 0x3e, }; + +static const char data_files_footer_plain[] = { + /* /files_footer.plain */ + 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, + 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, + 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, + 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; + +static const char data_files_header_html[] = { + /* /files_header.html */ + 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, + 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, + 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, + 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x30, 0x30, 0x22, 0x20, + 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, + 0x3e, 0xa, }; + static const char data_index_html[] = { /* /index.html */ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, - 0x2e, 0x35, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, @@ -103,147 +426,36 @@ static const char data_index_html[] = { 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, - 0x3e, 0xa, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, - 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, - 0x74, 0x65, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, - 0x35, 0x34, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, - 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, - 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, - 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0x3c, 0x74, - 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x3d, 0x22, 0x35, 0x33, 0x30, 0x22, 0x20, 0x62, - 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x63, - 0x30, 0x63, 0x30, 0x66, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x64, - 0x69, 0x76, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, - 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x3c, 0x62, 0x3e, - 0x75, 0x49, 0x50, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, - 0x70, 0x61, 0x67, 0x65, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, - 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, - 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x3d, 0x22, 0x31, 0x30, 0x22, 0x3e, 0x26, 0x6e, 0x62, 0x73, - 0x70, 0x3b, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, - 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x20, 0x76, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x22, - 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x62, 0x67, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x63, 0x30, 0x63, 0x30, - 0x66, 0x30, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x35, 0x33, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, - 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x31, 0x30, 0x22, - 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, - 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, - 0x30, 0x30, 0x25, 0x22, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0x3c, - 0x74, 0x64, 0x3e, 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, - 0x66, 0x79, 0x22, 0x3e, 0xa, 0x54, 0x68, 0x69, 0x73, 0x20, - 0x69, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6d, 0x70, 0x6c, - 0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x70, 0x61, 0x67, - 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x48, 0x54, 0x54, 0x50, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, - 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0xa, 0x75, 0x49, 0x50, 0x20, 0x54, 0x43, - 0x50, 0x2f, 0x49, 0x50, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, - 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61, 0x67, - 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0xa, 0x3c, 0x2f, 0x70, - 0x3e, 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, - 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, - 0x22, 0x3e, 0xa, 0x54, 0x68, 0x65, 0x20, 0x77, 0x65, 0x62, - 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, - 0x73, 0x6f, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, - 0x73, 0x20, 0x61, 0x20, 0x66, 0x65, 0x77, 0x20, 0x76, 0x69, - 0x72, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x67, 0x65, - 0x73, 0x3a, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x6c, 0x69, - 0x3e, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, - 0x22, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x22, 0x3e, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x77, 0x68, - 0x69, 0x63, 0x68, 0x20, 0x73, 0x68, 0x6f, 0x77, 0x73, 0x20, - 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, - 0x20, 0x70, 0x61, 0x67, 0x65, 0xa, 0x68, 0x69, 0x74, 0x73, - 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x6c, 0x69, - 0x3e, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, - 0x22, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x74, 0x63, 0x70, 0x22, - 0x3e, 0x2f, 0x63, 0x67, 0x69, 0x2f, 0x74, 0x63, 0x70, 0x3c, - 0x2f, 0x61, 0x3e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, - 0x73, 0x68, 0x6f, 0x77, 0x73, 0x20, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x20, 0x54, 0x43, 0x50, 0x20, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0xa, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x3c, 0x62, 0x72, 0x3e, - 0x20, 0xa, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0xa, 0x3c, 0x61, - 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x63, 0x67, - 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x3e, 0x2f, - 0x63, 0x67, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x3c, - 0x2f, 0x61, 0x3e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, - 0x73, 0x68, 0x6f, 0x77, 0x73, 0x20, 0x75, 0x49, 0x50, 0x20, - 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0xa, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0x3c, 0x62, - 0x72, 0x3e, 0x20, 0x20, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, - 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, - 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, - 0xa, 0x46, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, - 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, - 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, - 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x22, 0x3e, - 0x75, 0x49, 0x50, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x68, 0x6f, - 0x6d, 0x65, 0x20, 0x70, 0x61, 0x67, 0x65, 0x2e, 0xa, 0x3c, - 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x22, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, - 0x65, 0x3d, 0x22, 0x2d, 0x31, 0x22, 0x3e, 0x3c, 0x69, 0x3e, - 0xa, 0x24, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x32, 0x30, - 0x30, 0x31, 0x2f, 0x31, 0x31, 0x2f, 0x32, 0x34, 0x20, 0x31, - 0x35, 0x3a, 0x34, 0x33, 0x3a, 0x33, 0x36, 0x20, 0x24, 0xa, - 0x3c, 0x2f, 0x69, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, - 0x3e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0xa, 0x3c, - 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, - 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x2f, 0x74, - 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x3d, 0x22, 0x31, 0x30, 0x22, 0x20, 0x62, 0x67, - 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x61, 0x30, - 0x61, 0x30, 0x65, 0x33, 0x22, 0x3e, 0x26, 0x6e, 0x62, 0x73, - 0x70, 0x3b, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, - 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x34, 0x30, - 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, - 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, - 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, - 0x22, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, - 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x3d, 0x22, 0x31, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x2f, 0x74, - 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x3d, 0x22, 0x35, 0x33, 0x30, 0x22, 0x20, 0x62, - 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x61, - 0x30, 0x61, 0x30, 0x65, 0x33, 0x22, 0x3e, 0x3c, 0x64, 0x69, - 0x76, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0xa, 0x3c, 0x66, 0x6f, - 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, - 0x32, 0x22, 0x3e, 0x26, 0x63, 0x6f, 0x70, 0x79, 0x3b, 0xa, - 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, - 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, - 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, - 0x61, 0x6d, 0x2f, 0x22, 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, - 0x44, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x3c, 0x2f, 0x61, - 0x3e, 0x20, 0x32, 0x30, 0x30, 0x31, 0x3c, 0x2f, 0x66, 0x6f, - 0x6e, 0x74, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0xa, 0x3e, - 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, - 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, - 0xa, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, - 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; + 0x3e, 0xa, 0xa, 0x3c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, + 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x73, 0x3d, 0x22, 0x2a, + 0x22, 0x20, 0x72, 0x6f, 0x77, 0x73, 0x3d, 0x22, 0x31, 0x32, + 0x30, 0x2c, 0x2a, 0x22, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, + 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x6e, 0x6f, + 0x22, 0x3e, 0x20, 0xa, 0x20, 0x20, 0x3c, 0x66, 0x72, 0x61, + 0x6d, 0x65, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, + 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x66, 0x72, 0x61, 0x6d, + 0x65, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x61, 0x62, 0x6f, + 0x75, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x20, 0x6e, + 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x22, + 0x3e, 0xa, 0x3c, 0x2f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, + 0x65, 0x74, 0x3e, 0xa, 0xa, 0x3c, 0x6e, 0x6f, 0x66, 0x72, + 0x61, 0x6d, 0x65, 0x73, 0x3e, 0xa, 0x3c, 0x62, 0x6f, 0x64, + 0x79, 0x3e, 0xa, 0x59, 0x6f, 0x75, 0x72, 0x20, 0x62, 0x72, + 0x6f, 0x77, 0x73, 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, + 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x66, + 0x72, 0x61, 0x6d, 0x65, 0x73, 0xa, 0x3c, 0x2f, 0x62, 0x6f, + 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x6e, 0x6f, 0x66, 0x72, + 0x61, 0x6d, 0x65, 0x73, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, + 0x6d, 0x6c, 0x3e, }; + +static const char data_stats_footer_plain[] = { + /* /stats_footer.plain */ + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, + 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, + 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, + 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; static const char data_stats_header_html[] = { /* /stats_header.html */ @@ -251,183 +463,98 @@ static const char data_stats_header_html[] = { 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, - 0x2e, 0x35, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, - 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x3e, 0x75, 0x49, 0x50, 0x20, 0x54, 0x43, 0x50, 0x2f, - 0x49, 0x50, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, - 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, - 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x34, 0x30, - 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, - 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, - 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, - 0x22, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x3d, 0x22, 0x30, 0x22, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa, - 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x35, 0x33, 0x30, 0x22, 0x20, 0x62, 0x67, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x63, 0x30, 0x63, 0x30, - 0x66, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, - 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, - 0x68, 0x74, 0x22, 0x3e, 0x3c, 0x62, 0x3e, 0x75, 0x49, 0x50, - 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, - 0x62, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, - 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, - 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x30, 0x22, 0x3e, - 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x3c, 0x2f, 0x74, 0x64, - 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, - 0x72, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, - 0x74, 0x6f, 0x70, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, - 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, - 0x63, 0x30, 0x63, 0x30, 0x66, 0x30, 0x22, 0x20, 0x77, 0x69, - 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x33, 0x30, 0x22, 0x3e, - 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x65, - 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, - 0x22, 0x31, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, - 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0x3c, - 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0xa, 0x3c, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x3d, 0x22, 0x38, 0x30, 0x25, 0x22, 0x20, 0x63, 0x65, 0x6c, - 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, - 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x62, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e, - 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c, - 0x70, 0x72, 0x65, 0x3e, 0xa, 0x49, 0x50, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, - 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, 0x72, 0x6f, 0x70, - 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, - 0x49, 0x50, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, - 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0xa, 0x20, 0x20, + 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x30, 0x30, 0x22, 0x20, + 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, + 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, + 0xa, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x49, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x2c, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x62, 0x79, 0x74, - 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x6c, 0x6f, 0x77, 0x20, - 0x62, 0x79, 0x74, 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, - 0x20, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, 0x72, + 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, + 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, + 0x74, 0xa, 0x49, 0x50, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x73, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0xa, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x2c, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x62, + 0x79, 0x74, 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, + 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x6c, 0x6f, + 0x77, 0x20, 0x62, 0x79, 0x74, 0x65, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x49, 0x50, 0x20, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, + 0x6d, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x72, 0x6f, 0x6e, 0x67, + 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0xa, + 0x49, 0x43, 0x4d, 0x50, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, 0x72, + 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, + 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, + 0x74, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x54, 0x43, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, 0x72, + 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, + 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, + 0x74, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x75, 0x6d, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0xa, + 0x20, 0x20, 0x20, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x70, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x6f, 0x75, 0x74, 0x20, 0x41, 0x43, 0x4b, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0xa, 0x49, 0x43, - 0x4d, 0x50, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, - 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, 0x72, 0x6f, 0x70, - 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, + 0x20, 0x20, 0x20, 0x52, 0x65, 0x73, 0x65, 0x74, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x73, 0xa, 0x54, 0x43, 0x50, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, - 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, 0x72, 0x6f, 0x70, - 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, - 0x6d, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x70, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, - 0x75, 0x74, 0x20, 0x41, 0x43, 0x4b, 0x73, 0xa, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x52, 0x65, 0x73, 0x65, 0x74, 0x73, 0xa, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0xa, 0x9, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x76, 0x61, - 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0xa, 0x9, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, - 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x6f, 0x73, - 0x65, 0x64, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x73, 0xa, 0x3c, - 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x9, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, - 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, }; + 0x20, 0x20, 0x20, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0xa, 0x9, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x20, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x76, 0x61, 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0xa, 0x9, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x74, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6c, + 0x6f, 0x73, 0x65, 0x64, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x73, + 0xa, 0x3c, 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x9, 0x20, 0x20, + 0x20, 0x20, 0x20, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, }; -static const char data_stats_footer_plain[] = { - /* /stats_footer.plain */ - 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0, - 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, - 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, - 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0xa, - 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, - 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66, 0x6f, 0x6e, - 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x31, - 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44, 0x61, 0x74, - 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x31, 0x2f, 0x31, 0x31, - 0x2f, 0x32, 0x34, 0x20, 0x31, 0x35, 0x3a, 0x34, 0x33, 0x3a, - 0x33, 0x36, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69, 0x3e, 0x3c, - 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, 0x70, - 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, - 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, - 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, - 0x30, 0x22, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, - 0x3d, 0x22, 0x23, 0x61, 0x30, 0x61, 0x30, 0x65, 0x33, 0x22, - 0x3e, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x3c, 0x2f, 0x74, - 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x3d, 0x22, 0x35, 0x34, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, - 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, - 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x62, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e, - 0xa, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x30, 0x22, - 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, - 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, - 0x33, 0x30, 0x22, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, - 0x72, 0x3d, 0x22, 0x23, 0x61, 0x30, 0x61, 0x30, 0x65, 0x33, - 0x22, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, - 0x3e, 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x73, 0x69, - 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x32, 0x22, 0x3e, 0x26, 0x63, - 0x6f, 0x70, 0x79, 0x3b, 0xa, 0x43, 0x6f, 0x70, 0x79, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, - 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x22, 0x3e, - 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, 0x6b, 0x65, - 0x6c, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x32, 0x30, 0x30, - 0x31, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0x3c, 0x2f, - 0x64, 0x69, 0x76, 0xa, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, - 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x62, - 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, - 0x6c, 0x3e, 0xa, }; +static const char data_tcp_footer_plain[] = { + /* /tcp_footer.plain */ + 0x2f, 0x74, 0x63, 0x70, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0, + 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, + 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, + 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, + 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, + 0x68, 0x74, 0x6d, 0x6c, 0x3e, }; static const char data_tcp_header_html[] = { /* /tcp_header.html */ @@ -435,255 +562,58 @@ static const char data_tcp_header_html[] = { 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, - 0x2e, 0x35, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, - 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x3e, 0x75, 0x49, 0x50, 0x20, 0x54, 0x43, 0x50, 0x20, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x3c, 0x2f, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, - 0x64, 0x3e, 0xa, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, - 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, - 0x69, 0x74, 0x65, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x35, 0x34, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, - 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, - 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, - 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x62, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0x3c, - 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, - 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x33, 0x30, 0x22, 0x20, - 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, - 0x63, 0x30, 0x63, 0x30, 0x66, 0x30, 0x22, 0x3e, 0xa, 0x3c, - 0x64, 0x69, 0x76, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, - 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x3c, 0x62, - 0x3e, 0x75, 0x49, 0x50, 0x20, 0x54, 0x43, 0x50, 0x20, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x3c, 0x2f, 0x62, 0x3e, - 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f, 0x74, - 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x3d, 0x22, 0x31, 0x30, 0x22, 0x3e, 0x26, 0x6e, - 0x62, 0x73, 0x70, 0x3b, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, - 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x20, - 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x74, 0x6f, - 0x70, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x62, 0x67, - 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x63, 0x30, - 0x63, 0x30, 0x66, 0x30, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x3d, 0x22, 0x35, 0x33, 0x30, 0x22, 0x3e, 0xa, 0x3c, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x65, 0x6c, 0x6c, - 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x31, - 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, - 0x22, 0x30, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0x3c, 0x74, 0x72, - 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0xa, 0x3c, 0x63, 0x65, - 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x38, 0x30, 0x25, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, - 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x31, - 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, - 0x68, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3c, 0x2f, - 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, - 0x3e, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x74, 0x68, - 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x54, 0x69, 0x6d, 0x65, 0x72, - 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x46, - 0x6c, 0x61, 0x67, 0x73, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, - 0x2f, 0x74, 0x72, 0x3e, 0xa, 0xa, }; - -static const char data_files_footer_plain[] = { - /* /files_footer.plain */ - 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0, - 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, - 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, - 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, - 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66, 0x6f, - 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, - 0x31, 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44, 0x61, - 0x74, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x31, 0x2f, 0x31, - 0x31, 0x2f, 0x32, 0x34, 0x20, 0x31, 0x35, 0x3a, 0x34, 0x33, - 0x3a, 0x33, 0x36, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69, 0x3e, - 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, - 0x70, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, - 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, - 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, - 0x31, 0x30, 0x22, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, - 0x72, 0x3d, 0x22, 0x23, 0x61, 0x30, 0x61, 0x30, 0x65, 0x33, - 0x22, 0x3e, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x3c, 0x2f, - 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, - 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x3d, 0x22, 0x35, 0x34, 0x30, 0x22, 0x20, 0x63, 0x65, - 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, - 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, - 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x30, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, - 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, - 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x30, - 0x22, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, - 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, - 0x35, 0x33, 0x30, 0x22, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, - 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x61, 0x30, 0x61, 0x30, 0x65, - 0x33, 0x22, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x22, 0x3e, 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x73, - 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x32, 0x22, 0x3e, 0x26, - 0x63, 0x6f, 0x70, 0x79, 0x3b, 0xa, 0x43, 0x6f, 0x70, 0x79, - 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3c, 0x61, 0x20, 0x68, - 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, - 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x22, - 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, 0x6b, - 0x65, 0x6c, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x32, 0x30, - 0x30, 0x31, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0x3c, - 0x2f, 0x64, 0x69, 0x76, 0xa, 0x3e, 0x3c, 0x2f, 0x74, 0x64, - 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x2f, - 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, - 0x6d, 0x6c, 0x3e, 0xa, }; + 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x68, 0x3e, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, + 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x52, + 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, + 0x74, 0x68, 0x3e, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x46, 0x6c, 0x61, + 0x67, 0x73, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x2f, 0x74, + 0x72, 0x3e, 0xa, 0xa, }; -static const char data_files_header_html[] = { - /* /files_header.html */ - 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, - 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, - 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, - 0x2e, 0x35, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, - 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, - 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, - 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, - 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x3e, 0x75, 0x49, 0x50, 0x20, 0x77, 0x65, 0x62, 0x20, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x70, 0x61, 0x67, - 0x65, 0x20, 0x68, 0x69, 0x74, 0x73, 0x3c, 0x2f, 0x74, 0x69, - 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, - 0x3e, 0xa, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, - 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, - 0x74, 0x65, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, - 0x35, 0x34, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, - 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, - 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, - 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0x3c, 0x74, - 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x3d, 0x22, 0x35, 0x33, 0x30, 0x22, 0x20, 0x62, - 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x63, - 0x30, 0x63, 0x30, 0x66, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x64, - 0x69, 0x76, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, - 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x3c, 0x62, 0x3e, - 0x75, 0x49, 0x50, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x20, 0x70, 0x61, 0x67, 0x65, 0x20, - 0x68, 0x69, 0x74, 0x73, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, - 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, - 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x3d, 0x22, 0x31, 0x30, 0x22, 0x3e, 0x26, 0x6e, 0x62, 0x73, - 0x70, 0x3b, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, - 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x20, 0x76, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x22, - 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x62, 0x67, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x63, 0x30, 0x63, 0x30, - 0x66, 0x30, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x35, 0x33, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, - 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x31, 0x30, 0x22, - 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, - 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, - 0x30, 0x30, 0x25, 0x22, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0x3c, - 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, - 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x38, 0x30, 0x25, - 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, - 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x31, 0x30, 0x22, 0x20, 0x63, - 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, - 0x3d, 0x22, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, - 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, }; +const struct fsdata_file file_cgi_files[] = {{NULL, data_cgi_files, data_cgi_files + 11, sizeof(data_cgi_files) - 11}}; -static const char data_tcp_footer_plain[] = { - /* /tcp_footer.plain */ - 0x2f, 0x74, 0x63, 0x70, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0, - 0xa, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, - 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, - 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, - 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66, - 0x6f, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, - 0x2d, 0x31, 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44, - 0x61, 0x74, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x31, 0x2f, - 0x31, 0x31, 0x2f, 0x32, 0x34, 0x20, 0x31, 0x35, 0x3a, 0x34, - 0x33, 0x3a, 0x33, 0x36, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69, - 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, - 0x2f, 0x70, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x72, - 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, - 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x31, 0x30, 0x22, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, - 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x61, 0x30, 0x61, 0x30, 0x65, - 0x33, 0x22, 0x3e, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x3c, - 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, - 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, - 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x3d, 0x22, 0x35, 0x34, 0x30, 0x22, 0x20, 0x63, - 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, - 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, - 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, - 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, - 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, - 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, - 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, - 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, - 0x22, 0x35, 0x33, 0x30, 0x22, 0x20, 0x62, 0x67, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x61, 0x30, 0x61, 0x30, - 0x65, 0x33, 0x22, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, - 0x74, 0x22, 0x3e, 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, - 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x32, 0x22, 0x3e, - 0x26, 0x63, 0x6f, 0x70, 0x79, 0x3b, 0xa, 0x43, 0x6f, 0x70, - 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3c, 0x61, 0x20, - 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, - 0x22, 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, - 0x6b, 0x65, 0x6c, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x32, - 0x30, 0x30, 0x31, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, - 0x3c, 0x2f, 0x64, 0x69, 0x76, 0xa, 0x3e, 0x3c, 0x2f, 0x74, - 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, - 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, - 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, - 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; +const struct fsdata_file file_cgi_stats[] = {{file_cgi_files, data_cgi_stats, data_cgi_stats + 11, sizeof(data_cgi_stats) - 11}}; -const struct fsdata_file file_cgi_stats[] = {{NULL, data_cgi_stats, data_cgi_stats + 11, sizeof(data_cgi_stats) - 11}}; +const struct fsdata_file file_cgi_tcp[] = {{file_cgi_stats, data_cgi_tcp, data_cgi_tcp + 9, sizeof(data_cgi_tcp) - 9}}; -const struct fsdata_file file_cgi_files[] = {{file_cgi_stats, data_cgi_files, data_cgi_files + 11, sizeof(data_cgi_files) - 11}}; +const struct fsdata_file file_img_bg_png[] = {{file_cgi_tcp, data_img_bg_png, data_img_bg_png + 12, sizeof(data_img_bg_png) - 12}}; -const struct fsdata_file file_cgi_tcp[] = {{file_cgi_files, data_cgi_tcp, data_cgi_tcp + 9, sizeof(data_cgi_tcp) - 9}}; +const struct fsdata_file file_about_html[] = {{file_img_bg_png, data_about_html, data_about_html + 12, sizeof(data_about_html) - 12}}; -const struct fsdata_file file_index_html[] = {{file_cgi_tcp, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; +const struct fsdata_file file_control_html[] = {{file_about_html, data_control_html, data_control_html + 14, sizeof(data_control_html) - 14}}; -const struct fsdata_file file_stats_header_html[] = {{file_index_html, data_stats_header_html, data_stats_header_html + 19, sizeof(data_stats_header_html) - 19}}; +const struct fsdata_file file_404_html[] = {{file_control_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; -const struct fsdata_file file_stats_footer_plain[] = {{file_stats_header_html, data_stats_footer_plain, data_stats_footer_plain + 20, sizeof(data_stats_footer_plain) - 20}}; - -const struct fsdata_file file_tcp_header_html[] = {{file_stats_footer_plain, data_tcp_header_html, data_tcp_header_html + 17, sizeof(data_tcp_header_html) - 17}}; - -const struct fsdata_file file_files_footer_plain[] = {{file_tcp_header_html, data_files_footer_plain, data_files_footer_plain + 20, sizeof(data_files_footer_plain) - 20}}; +const struct fsdata_file file_files_footer_plain[] = {{file_404_html, data_files_footer_plain, data_files_footer_plain + 20, sizeof(data_files_footer_plain) - 20}}; const struct fsdata_file file_files_header_html[] = {{file_files_footer_plain, data_files_header_html, data_files_header_html + 19, sizeof(data_files_header_html) - 19}}; -const struct fsdata_file file_tcp_footer_plain[] = {{file_files_header_html, data_tcp_footer_plain, data_tcp_footer_plain + 18, sizeof(data_tcp_footer_plain) - 18}}; +const struct fsdata_file file_index_html[] = {{file_files_header_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; -#define FS_ROOT file_tcp_footer_plain +const struct fsdata_file file_stats_footer_plain[] = {{file_index_html, data_stats_footer_plain, data_stats_footer_plain + 20, sizeof(data_stats_footer_plain) - 20}}; -#define FS_NUMFILES 10 \ No newline at end of file +const struct fsdata_file file_stats_header_html[] = {{file_stats_footer_plain, data_stats_header_html, data_stats_header_html + 19, sizeof(data_stats_header_html) - 19}}; + +const struct fsdata_file file_tcp_footer_plain[] = {{file_stats_header_html, data_tcp_footer_plain, data_tcp_footer_plain + 18, sizeof(data_tcp_footer_plain) - 18}}; + +const struct fsdata_file file_tcp_header_html[] = {{file_tcp_footer_plain, data_tcp_header_html, data_tcp_header_html + 17, sizeof(data_tcp_header_html) - 17}}; + +#define FS_ROOT file_tcp_header_html + +#define FS_NUMFILES 14 \ No newline at end of file diff --git a/apps/httpd/fsdata.h b/apps/httpd/fsdata.h index 8b0c6f2..e525f4e 100644 --- a/apps/httpd/fsdata.h +++ b/apps/httpd/fsdata.h @@ -10,11 +10,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Swedish Institute - * of Computer Science and its contributors. - * 4. Neither the name of the Institute nor the names of its contributors + * 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. * @@ -34,7 +30,7 @@ * * Author: Adam Dunkels * - * $Id: fsdata.h,v 1.4 2001/11/25 18:47:36 adam Exp $ + * $Id: fsdata.h,v 1.4.2.1 2003/10/04 22:54:06 adam Exp $ */ #ifndef __FSDATA_H__ #define __FSDATA_H__ diff --git a/apps/httpd/httpd.c b/apps/httpd/httpd.c index 1c821ea..ad927d0 100644 --- a/apps/httpd/httpd.c +++ b/apps/httpd/httpd.c @@ -1,3 +1,54 @@ +/** + * \addtogroup exampleapps + * @{ + */ + +/** + * \defgroup httpd Web server + * @{ + * + * The uIP web server is a very simplistic implementation of an HTTP + * server. It can serve web pages and files from a read-only ROM + * filesystem, and provides a very small scripting language. + * + * The script language is very simple and works as follows. Each + * script line starts with a command character, either "i", "t", "c", + * "#" or ".". The "i" command tells the script interpreter to + * "include" a file from the virtual file system and output it to the + * web browser. The "t" command should be followed by a line of text + * that is to be output to the browser. The "c" command is used to + * call one of the C functions from the httpd-cgi.c file. A line that + * starts with a "#" is ignored (i.e., the "#" denotes a comment), and + * the "." denotes the last script line. + * + * The script that produces the file statistics page looks somewhat + * like this: + * + \code +i /header.html +t

    File statistics


    RemoteStateRetransmissionsTimerFlags
    +t
    /index.html +c a /index.html +t
    /cgi/files +c a /cgi/files +t
    /cgi/tcp +c a /cgi/tcp +t
    /404.html +c a /404.html +t
    +i /footer.plain +. + \endcode + * + */ + + +/** + * \file + * HTTP server. + * \author Adam Dunkels + */ + /* * Copyright (c) 2001, Adam Dunkels. * All rights reserved. @@ -10,10 +61,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +79,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: httpd.c,v 1.27 2002/01/15 17:22:08 adam Exp $ + * $Id: httpd.c,v 1.28.2.6 2003/10/07 13:22:27 adam Exp $ * */ @@ -63,6 +111,7 @@ struct httpd_state *hs; extern const struct fsdata_file file_index_html; +extern const struct fsdata_file file_404_html; static void next_scriptline(void); static void next_scriptstate(void); @@ -83,6 +132,12 @@ static void next_scriptstate(void); #define ISO_period 0x2e +/*-----------------------------------------------------------------------------------*/ +/** + * Initialize the web server. + * + * Starts to listen for incoming connection requests on TCP port 80. + */ /*-----------------------------------------------------------------------------------*/ void httpd_init(void) @@ -90,18 +145,19 @@ httpd_init(void) fs_init(); /* Listen to port 80. */ - uip_listen(80); + uip_listen(HTONS(80)); } /*-----------------------------------------------------------------------------------*/ void -httpd(void) +httpd_appcall(void) { struct fs_file fsfile; + u8_t i; - + switch(uip_conn->lport) { /* This is the web server: */ - case htons(80): + case HTONS(80): /* Pick out the application state from the uip_conn structure. */ hs = (struct httpd_state *)(uip_conn->appstate); @@ -121,9 +177,6 @@ httpd(void) connection yet. */ hs->state = HTTP_NOGET; hs->count = 0; - /* Don't send any data in return; we wait for the HTTP request - instead. */ - uip_send(uip_appdata, 0); return; } else if(uip_poll()) { @@ -161,11 +214,18 @@ httpd(void) PRINT("request for file "); PRINTLN(&uip_appdata[4]); - if(!fs_open((const char *)&uip_appdata[4], &fsfile)) { - PRINTLN("couldn't open file"); - fs_open(file_index_html.name, &fsfile); + /* Check for a request for "/". */ + if(uip_appdata[4] == ISO_slash && + uip_appdata[5] == 0) { + fs_open(file_index_html.name, &fsfile); + } else { + if(!fs_open((const char *)&uip_appdata[4], &fsfile)) { + PRINTLN("couldn't open file"); + fs_open(file_404_html.name, &fsfile); + } } + if(uip_appdata[4] == ISO_slash && uip_appdata[5] == ISO_c && uip_appdata[6] == ISO_g && @@ -196,10 +256,9 @@ httpd(void) into the file and send back more data. If we are out of data to send, we close the connection. */ if(uip_acked()) { - - if(hs->count >= uip_mss()) { - hs->count -= uip_mss(); - hs->dataptr += uip_mss(); + if(hs->count >= uip_conn->len) { + hs->count -= uip_conn->len; + hs->dataptr += uip_conn->len; } else { hs->count = 0; } @@ -213,11 +272,9 @@ httpd(void) } } } - } - - if(hs->state == HTTP_FUNC) { + } else { /* Call the CGI function. */ - if(cgitab[hs->script[2] - ISO_a]()) { + if(cgitab[hs->script[2] - ISO_a](uip_acked())) { /* If the function returns non-zero, we jump to the next line in the script. */ next_scriptline(); @@ -228,8 +285,7 @@ httpd(void) if(hs->state != HTTP_FUNC && !uip_poll()) { /* Send a piece of data, but not more than the MSS of the connection. */ - uip_send(hs->dataptr, - hs->count > uip_mss()? uip_mss(): hs->count); + uip_send(hs->dataptr, hs->count); } /* Finally, return to uIP. Our outgoing packet will soon be on its @@ -284,7 +340,7 @@ next_scriptstate(void) hs->state = HTTP_FUNC; hs->dataptr = NULL; hs->count = 0; - uip_reset_acked(); + cgitab[hs->script[2] - ISO_a](0); break; case ISO_i: /* Include a file. */ @@ -311,3 +367,5 @@ next_scriptstate(void) } } /*-----------------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/apps/httpd/httpd.h b/apps/httpd/httpd.h index a0a7f87..a56221c 100644 --- a/apps/httpd/httpd.h +++ b/apps/httpd/httpd.h @@ -1,3 +1,14 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * HTTP server header file. + * \author Adam Dunkels + */ + /* * Copyright (c) 2001, Adam Dunkels. * All rights reserved. @@ -10,10 +21,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +39,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: httpd.h,v 1.3 2002/01/15 17:22:08 adam Exp $ + * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $ * */ @@ -39,12 +47,14 @@ #define __HTTPD_H__ void httpd_init(void); -void httpd(void); +void httpd_appcall(void); /* UIP_APPCALL: the name of the application function. This function must return void and take no arguments (i.e., C type "void appfunc(void)"). */ -#define UIP_APPCALL httpd +#ifndef UIP_APPCALL +#define UIP_APPCALL httpd_appcall +#endif struct httpd_state { u8_t state; @@ -56,7 +66,9 @@ struct httpd_state { /* UIP_APPSTATE_SIZE: The size of the application-specific state stored in the uip_conn structure. */ +#ifndef UIP_APPSTATE_SIZE #define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) +#endif #define FS_STATISTICS 1 diff --git a/apps/httpd/makefsdata b/apps/httpd/makefsdata index cfbe920..cc655f3 100755 --- a/apps/httpd/makefsdata +++ b/apps/httpd/makefsdata @@ -15,8 +15,12 @@ while($file = ) { chop($file); open(HEADER, "> /tmp/header") || die $!; - print(HEADER "HTTP/1.0 200 OK\r\n"); - print(HEADER "Server: uIP/0.5 (http://dunkels.com/adam/uip/)\r\n"); + if($file =~ /404.html/) { + print(HEADER "HTTP/1.0 404 File not found\r\n"); + } else { + print(HEADER "HTTP/1.0 200 OK\r\n"); + } + print(HEADER "Server: uIP/0.9 (http://dunkels.com/adam/uip/)\r\n"); if($file =~ /\.html$/) { print(HEADER "Content-type: text/html\r\n"); } elsif($file =~ /\.gif$/) { diff --git a/apps/resolv/resolv.c b/apps/resolv/resolv.c new file mode 100644 index 0000000..f068e5c --- /dev/null +++ b/apps/resolv/resolv.c @@ -0,0 +1,467 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uipdns uIP hostname resolver functions + * @{ + * + * The uIP DNS resolver functions are used to lookup a hostname and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the resolv_lookup() + * function. New hostnames can be resolved using the resolv_query() + * function. + * + * When a hostname has been resolved (or found to be non-existant), + * the resolver code calls a callback function called resolv_found() + * that must be implemented by the module that uses the resolver. + */ + +/** + * \file + * DNS host name to IP address resolver. + * \author Adam Dunkels + * + * This file implements a DNS host name to IP address resolver. + */ + +/* + * Copyright (c) 2002-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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: resolv.c,v 1.1.2.5 2003/10/06 22:56:44 adam Exp $ + * + */ + +#include "resolv.h" + +#include + +#ifndef NULL +#define NULL (void *)0 +#endif /* NULL */ + +/** \internal The maximum number of retries when asking for a name. */ +#define MAX_RETRIES 8 + +/** \internal The DNS message header. */ +struct dns_hdr { + u16_t id; + u8_t flags1, flags2; +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + u16_t numquestions; + u16_t numanswers; + u16_t numauthrr; + u16_t numextrarr; +}; + +/** \internal The DNS answer message structure. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t class; + u16_t ttl[2]; + u16_t len; + u16_t ipaddr[2]; +}; + +struct namemap { +#define STATE_UNUSED 0 +#define STATE_NEW 1 +#define STATE_ASKING 2 +#define STATE_DONE 3 +#define STATE_ERROR 4 + u8_t state; + u8_t tmr; + u8_t retries; + u8_t seqno; + u8_t err; + char name[32]; + u16_t ipaddr[2]; +}; + +#ifndef UIP_CONF_RESOLV_ENTRIES +#define RESOLV_ENTRIES 4 +#else /* UIP_CONF_RESOLV_ENTRIES */ +#define RESOLV_ENTRIES UIP_CONF_RESOLV_ENTRIES +#endif /* UIP_CONF_RESOLV_ENTRIES */ + + +static struct namemap names[RESOLV_ENTRIES]; + +static u8_t seqno; + +static struct uip_udp_conn *resolv_conn = NULL; + + +/*-----------------------------------------------------------------------------------*/ +/** \internal + * Walk through a compact encoded DNS name and return the end of it. + * + * \return The end of the name. + */ +/*-----------------------------------------------------------------------------------*/ +static unsigned char * +parse_name(unsigned char *query) +{ + unsigned char n; + + do { + n = *query++; + + while(n > 0) { + /* printf("%c", *query);*/ + ++query; + --n; + }; + /* printf(".");*/ + } while(*query != 0); + /* printf("\n");*/ + return query + 1; +} +/*-----------------------------------------------------------------------------------*/ +/** \internal + * Runs through the list of names to see if there are any that have + * not yet been queried and, if so, sends out a query. + */ +/*-----------------------------------------------------------------------------------*/ +static void +check_entries(void) +{ + register struct dns_hdr *hdr; + char *query, *nptr, *nameptr; + static u8_t i; + static u8_t n; + register struct namemap *namemapptr; + + for(i = 0; i < RESOLV_ENTRIES; ++i) { + namemapptr = &names[i]; + if(namemapptr->state == STATE_NEW || + namemapptr->state == STATE_ASKING) { + if(namemapptr->state == STATE_ASKING) { + if(--namemapptr->tmr == 0) { + if(++namemapptr->retries == MAX_RETRIES) { + namemapptr->state = STATE_ERROR; + resolv_found(namemapptr->name, NULL); + continue; + } + namemapptr->tmr = namemapptr->retries; + } else { + /* printf("Timer %d\n", namemapptr->tmr);*/ + /* Its timer has not run out, so we move on to next + entry. */ + continue; + } + } else { + namemapptr->state = STATE_ASKING; + namemapptr->tmr = 1; + namemapptr->retries = 0; + } + hdr = (struct dns_hdr *)uip_appdata; + memset(hdr, 0, sizeof(struct dns_hdr)); + hdr->id = htons(i); + hdr->flags1 = DNS_FLAG1_RD; + hdr->numquestions = HTONS(1); + query = (char *)uip_appdata + 12; + nameptr = namemapptr->name; + --nameptr; + /* Convert hostname into suitable query format. */ + do { + ++nameptr; + nptr = query; + ++query; + for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) { + *query = *nameptr; + ++query; + ++n; + } + *nptr = n; + } while(*nameptr != 0); + { + static unsigned char endquery[] = + {0,0,1,0,1}; + memcpy(query, endquery, 5); + } + uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata)); + break; + } + } +} +/*-----------------------------------------------------------------------------------*/ +/** \internal + * Called when new UDP data arrives. + */ +/*-----------------------------------------------------------------------------------*/ +static void +newdata(void) +{ + char *nameptr; + struct dns_answer *ans; + struct dns_hdr *hdr; + static u8_t nquestions, nanswers; + static u8_t i; + register struct namemap *namemapptr; + + hdr = (struct dns_hdr *)uip_appdata; + /* printf("ID %d\n", htons(hdr->id)); + printf("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE); + printf("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK); + printf("Num questions %d, answers %d, authrr %d, extrarr %d\n", + htons(hdr->numquestions), + htons(hdr->numanswers), + htons(hdr->numauthrr), + htons(hdr->numextrarr)); + */ + + /* The ID in the DNS header should be our entry into the name + table. */ + i = htons(hdr->id); + namemapptr = &names[i]; + if(i < RESOLV_ENTRIES && + namemapptr->state == STATE_ASKING) { + + /* This entry is now finished. */ + namemapptr->state = STATE_DONE; + namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; + + /* Check for error. If so, call callback to inform. */ + if(namemapptr->err != 0) { + namemapptr->state = STATE_ERROR; + resolv_found(namemapptr->name, NULL); + return; + } + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = htons(hdr->numquestions); + nanswers = htons(hdr->numanswers); + + /* Skip the name in the question. XXX: This should really be + checked agains the name in the question, to be sure that they + match. */ + nameptr = parse_name((char *)uip_appdata + 12) + 4; + + while(nanswers > 0) { + /* The first byte in the answer resource record determines if it + is a compressed record or a normal one. */ + if(*nameptr & 0xc0) { + /* Compressed name. */ + nameptr +=2; + /* printf("Compressed anwser\n");*/ + } else { + /* Not compressed name. */ + nameptr = parse_name((char *)nameptr); + } + + ans = (struct dns_answer *)nameptr; + /* printf("Answer: type %x, class %x, ttl %x, length %x\n", + htons(ans->type), htons(ans->class), (htons(ans->ttl[0]) + << 16) | htons(ans->ttl[1]), htons(ans->len));*/ + + /* Check for IP address type and Internet class. Others are + discarded. */ + if(ans->type == HTONS(1) && + ans->class == HTONS(1) && + ans->len == HTONS(4)) { + /* printf("IP address %d.%d.%d.%d\n", + htons(ans->ipaddr[0]) >> 8, + htons(ans->ipaddr[0]) & 0xff, + htons(ans->ipaddr[1]) >> 8, + htons(ans->ipaddr[1]) & 0xff);*/ + /* XXX: we should really check that this IP address is the one + we want. */ + namemapptr->ipaddr[0] = ans->ipaddr[0]; + namemapptr->ipaddr[1] = ans->ipaddr[1]; + + resolv_found(namemapptr->name, namemapptr->ipaddr); + return; + } else { + nameptr = nameptr + 10 + htons(ans->len); + } + --nanswers; + } + } + +} +/*-----------------------------------------------------------------------------------*/ +/** \internal + * The main UDP function. + */ +/*-----------------------------------------------------------------------------------*/ +void +udp_appcall(void) +{ + if(uip_udp_conn->rport == HTONS(53)) { + if(uip_poll()) { + check_entries(); + } + if(uip_newdata()) { + newdata(); + } + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Queues a name so that a question for the name will be sent out. + * + * \param name The hostname that is to be queried. + */ +/*-----------------------------------------------------------------------------------*/ +void +resolv_query(char *name) +{ + static u8_t i; + static u8_t lseq, lseqi; + register struct namemap *nameptr; + + lseq = lseqi = 0; + + for(i = 0; i < RESOLV_ENTRIES; ++i) { + nameptr = &names[i]; + if(nameptr->state == STATE_UNUSED) { + break; + } + if(seqno - nameptr->seqno > lseq) { + lseq = seqno - nameptr->seqno; + lseqi = i; + } + } + + if(i == RESOLV_ENTRIES) { + i = lseqi; + nameptr = &names[i]; + } + + /* printf("Using entry %d\n", i);*/ + + strcpy(nameptr->name, name); + nameptr->state = STATE_NEW; + nameptr->seqno = seqno; + ++seqno; + + /* if(resolv_conn != NULL) { + dispatcher_emit(uip_signal_poll_udp, resolv_conn, DISPATCHER_BROADCAST); + } */ +} +/*-----------------------------------------------------------------------------------*/ +/** + * Look up a hostname in the array of known hostnames. + * + * \note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function resolv_query() can be used to send a query + * for a hostname. + * + * \return A pointer to a 4-byte representation of the hostname's IP + * address, or NULL if the hostname was not found in the array of + * hostnames. + */ +/*-----------------------------------------------------------------------------------*/ +u16_t * +resolv_lookup(char *name) +{ + static u8_t i; + struct namemap *nameptr; + + /* Walk through the list to see if the name is in there. If it is + not, we return NULL. */ + for(i = 0; i < RESOLV_ENTRIES; ++i) { + nameptr = &names[i]; + if(nameptr->state == STATE_DONE && + strcmp(name, nameptr->name) == 0) { + return nameptr->ipaddr; + } + } + return NULL; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Obtain the currently configured DNS server. + * + * \return A pointer to a 4-byte representation of the IP address of + * the currently configured DNS server or NULL if no DNS server has + * been configured. + */ +/*-----------------------------------------------------------------------------------*/ +u16_t * +resolv_getserver(void) +{ + if(resolv_conn == NULL) { + return NULL; + } + return resolv_conn->ripaddr; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Configure which DNS server to use for queries. + * + * \param dnsserver A pointer to a 4-byte representation of the IP + * address of the DNS server to be configured. + */ +/*-----------------------------------------------------------------------------------*/ +void +resolv_conf(u16_t *dnsserver) +{ + if(resolv_conn != NULL) { + uip_udp_remove(resolv_conn); + } + + resolv_conn = uip_udp_new(dnsserver, 53); +} +/*-----------------------------------------------------------------------------------*/ +/** + * Initalize the resolver. + */ +/*-----------------------------------------------------------------------------------*/ +void +resolv_init(void) +{ + static u8_t i; + + for(i = 0; i < RESOLV_ENTRIES; ++i) { + names[i].state = STATE_DONE; + } + +} +/*-----------------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ diff --git a/cc65/rs232dev.h b/apps/resolv/resolv.h similarity index 59% rename from cc65/rs232dev.h rename to apps/resolv/resolv.h index 175650a..06b723d 100644 --- a/cc65/rs232dev.h +++ b/apps/resolv/resolv.h @@ -1,5 +1,15 @@ +/** + * \addtogroup uipdns + * @{ + */ +/** + * \file + * DNS resolver code header file. + * \author Adam Dunkels + */ + /* - * Copyright (c) 2001, Adam Dunkels. + * Copyright (c) 2002-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +20,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,23 +38,34 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: rs232dev.h,v 1.1 2001/11/20 20:49:45 adam Exp $ + * $Id: resolv.h,v 1.1.2.3 2003/10/04 21:18:59 adam Exp $ * */ - -#ifndef __RS232DEV_H__ -#define __RS232DEV_H__ +#ifndef __RESOLV_H__ +#define __RESOLV_H__ #include "uip.h" -void rs232dev_init(void); -u8_t rs232dev_read(void); -void rs232dev_send(void); +/** + * Callback function which is called when a hostname is found. + * + * This function must be implemented by the module that uses the DNS + * resolver. It is called when a hostname is found, or when a hostname + * was not found. + * + * \param name A pointer to the name that was looked up. \param + * ipaddr A pointer to a 4-byte array containing the IP address of the + * hostname, or NULL if the hostname could not be found. + */ +void resolv_found(char *name, u16_t *ipaddr); -#if UIP_BUFSIZE > 255 -u16_t rs232dev_poll(void); -#else -u8_t rs232dev_poll(void); -#endif /* UIP_BUFSIZE > 255 */ +/* Functions. */ +void resolv_conf(u16_t *dnsserver); +u16_t *resolv_getserver(void); +void resolv_init(void); +u16_t *resolv_lookup(char *name); +void resolv_query(char *name); -#endif /* __RS232DEV_H__ */ +#endif /* __RESOLV_H__ */ + +/** @} */ diff --git a/apps/smtp/makesmtpstrings b/apps/smtp/makesmtpstrings new file mode 100755 index 0000000..720b358 --- /dev/null +++ b/apps/smtp/makesmtpstrings @@ -0,0 +1,27 @@ +#!/usr/bin/perl + +open(OUTPUTC, "> smtp-strings.c"); +open(OUTPUTH, "> smtp-strings.h"); + +open(FILE, "smtp-strings"); + +while() { + if(/(.+) "(.+)"/) { + $var = $1; + $data = $2; + + printf(OUTPUTC "char $var\[%d] = \n", length($data) + 1); + printf(OUTPUTC "/* $data */\n"); + printf(OUTPUTC "{"); + for($j = 0; $j < length($data); $j++) { + printf(OUTPUTC "%#02x, ", unpack("C", substr($data, $j, 1))); + } + printf(OUTPUTC "};\n"); + + printf(OUTPUTH "extern char $var\[%d];\n", length($data) + 1); + + } +} +exit 0; + +printf(OUTPUT "%#02x, ", unpack("C", $data)); diff --git a/apps/smtp/smtp-strings b/apps/smtp/smtp-strings new file mode 100644 index 0000000..a9e937c --- /dev/null +++ b/apps/smtp/smtp-strings @@ -0,0 +1,9 @@ +smtp_220 "220" +smtp_helo "HELO " +smtp_mail_from "MAIL FROM: " +smtp_rcpt_to "RCPT TO: " +smtp_data "DATA" +smtp_to "To: " +smtp_from "From: " +smtp_subject "Subject: " +smtp_quit "QUIT" \ No newline at end of file diff --git a/apps/smtp/smtp-strings.c b/apps/smtp/smtp-strings.c new file mode 100644 index 0000000..dde1efe --- /dev/null +++ b/apps/smtp/smtp-strings.c @@ -0,0 +1,27 @@ +char smtp_220[4] = +/* 220 */ +{0x32, 0x32, 0x30, }; +char smtp_helo[6] = +/* HELO */ +{0x48, 0x45, 0x4c, 0x4f, 0x20, }; +char smtp_mail_from[12] = +/* MAIL FROM: */ +{0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x20, }; +char smtp_rcpt_to[10] = +/* RCPT TO: */ +{0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, 0x20, }; +char smtp_data[5] = +/* DATA */ +{0x44, 0x41, 0x54, 0x41, }; +char smtp_to[5] = +/* To: */ +{0x54, 0x6f, 0x3a, 0x20, }; +char smtp_from[7] = +/* From: */ +{0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, }; +char smtp_subject[10] = +/* Subject: */ +{0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x20, }; +char smtp_quit[5] = +/* QUIT */ +{0x51, 0x55, 0x49, 0x54, }; diff --git a/apps/smtp/smtp-strings.h b/apps/smtp/smtp-strings.h new file mode 100644 index 0000000..15bed46 --- /dev/null +++ b/apps/smtp/smtp-strings.h @@ -0,0 +1,9 @@ +extern char smtp_220[4]; +extern char smtp_helo[6]; +extern char smtp_mail_from[12]; +extern char smtp_rcpt_to[10]; +extern char smtp_data[5]; +extern char smtp_to[5]; +extern char smtp_from[7]; +extern char smtp_subject[10]; +extern char smtp_quit[5]; diff --git a/apps/smtp/smtp.c b/apps/smtp/smtp.c new file mode 100644 index 0000000..fadfe2b --- /dev/null +++ b/apps/smtp/smtp.c @@ -0,0 +1,422 @@ +/** + * \addtogroup exampleapps + * @{ + */ + +/** + * \defgroup smtp SMTP E-mail sender + * @{ + * + * The Simple Mail Transfer Protocol (SMTP) as defined by RFC821 is + * the standard way of sending and transfering e-mail on the + * Internet. This simple example implementation is intended as an + * example of how to implement protocols in uIP, and is able to send + * out e-mail but has not been extensively tested. + */ + +/** + * \file + * SMTP example implementation + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2002, 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: smtp.c,v 1.1.2.7 2003/10/07 13:47:50 adam Exp $ + * + */ + +#include "uip.h" +#include "smtp.h" + +#include "smtp-strings.h" + +#include + +#define STATE_SEND_NONE 0 +#define STATE_SEND_HELO 1 +#define STATE_SEND_MAIL_FROM 2 +#define STATE_SEND_RCPT_TO 3 +#define STATE_SEND_DATA 4 +#define STATE_SEND_DATA_HEADERS 5 +#define STATE_SEND_DATA_MESSAGE 6 +#define STATE_SEND_DATA_END 7 +#define STATE_SEND_QUIT 8 +#define STATE_SEND_DONE 9 + +static char *localhostname; +static u16_t smtpserver[2]; + + + +#define ISO_nl 0x0a +#define ISO_cr 0x0d + +#define ISO_period 0x2e + +#define ISO_2 0x32 +#define ISO_3 0x33 +#define ISO_4 0x34 +#define ISO_5 0x35 + + + +/*-----------------------------------------------------------------------------------*/ +static void +senddata(struct smtp_state *s) +{ + char *textptr; + + if(s->textlen != 0 && + s->textlen == s->sendptr) { + return; + } + + textptr = (char *)uip_appdata; + switch(s->state) { + case STATE_SEND_HELO: + /* Create HELO message. */ + strcpy(textptr, smtp_helo); + textptr += sizeof(smtp_helo) - 1; + strcpy(textptr, localhostname); + textptr += strlen(localhostname); + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + /* printf("s->sendptr %d\n", s->sendptr);*/ + if(s->sendptr == 0) { + s->textlen = textptr - (char *)uip_appdata; + /* printf("s->textlen %d\n", s->textlen);*/ + } + textptr = (char *)uip_appdata; + break; + case STATE_SEND_MAIL_FROM: + /* Create MAIL FROM message. */ + strcpy(textptr, smtp_mail_from); + textptr += sizeof(smtp_mail_from) - 1; + strcpy(textptr, s->from); + textptr += strlen(s->from); + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + if(s->sendptr == 0) { + s->textlen = textptr - (char *)uip_appdata; + } + textptr = (char *)uip_appdata; + break; + case STATE_SEND_RCPT_TO: + /* Create RCPT_TO message. */ + strcpy(textptr, smtp_rcpt_to); + textptr += sizeof(smtp_rcpt_to) - 1; + strcpy(textptr, s->to); + textptr += strlen(s->to); + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + if(s->sendptr == 0) { + s->textlen = textptr - (char *)uip_appdata; + } + textptr = (char *)uip_appdata; + break; + case STATE_SEND_DATA: + strcpy(textptr, smtp_data); + textptr += sizeof(smtp_data) - 1; + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + if(s->sendptr == 0) { + s->textlen = textptr - (char *)uip_appdata; + } + textptr = (char *)uip_appdata; + break; + case STATE_SEND_DATA_HEADERS: + /* Create mail headers-> */ + strcpy(textptr, smtp_to); + textptr += sizeof(smtp_to) - 1; + strcpy(textptr, s->to); + textptr += strlen(s->to); + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + + strcpy(textptr, smtp_from); + textptr += sizeof(smtp_from) - 1; + strcpy(textptr, s->from); + textptr += strlen(s->from); + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + + strcpy(textptr, smtp_subject); + textptr += sizeof(smtp_subject) - 1; + strcpy(textptr, s->subject); + textptr += strlen(s->subject); + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + + if(s->sendptr == 0) { + s->textlen = textptr - (char *)uip_appdata; + } + textptr = (char *)uip_appdata; + break; + case STATE_SEND_DATA_MESSAGE: + textptr = s->msg; + if(s->sendptr == 0) { + s->textlen = s->msglen; + } + break; + case STATE_SEND_DATA_END: + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + *textptr = ISO_period; + ++textptr; + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + if(s->sendptr == 0) { + s->textlen = 5; + } + textptr = (char *)uip_appdata; + break; + case STATE_SEND_QUIT: + strcpy(textptr, smtp_quit); + textptr += sizeof(smtp_quit) - 1; + *textptr = ISO_cr; + ++textptr; + *textptr = ISO_nl; + ++textptr; + if(s->sendptr == 0) { + s->textlen = textptr - (char *)uip_appdata; + } + textptr = (char *)uip_appdata; + break; + default: + return; + } + + textptr += s->sendptr; + + if(s->textlen - s->sendptr > uip_mss()) { + s->sentlen = uip_mss(); + } else { + s->sentlen = s->textlen - s->sendptr; + } + + /* textptr[s->sentlen] = 0; + printf("Senidng '%s'\n", textptr);*/ + + uip_send(textptr, s->sentlen); +} +/*-----------------------------------------------------------------------------------*/ +static void +acked(struct smtp_state *s) +{ + s->sendptr += s->sentlen; + s->sentlen = 0; + + if(s->sendptr == s->textlen) { + switch(s->state) { + case STATE_SEND_DATA_HEADERS: + s->state = STATE_SEND_DATA_MESSAGE; + s->sendptr = s->textlen = 0; + break; + case STATE_SEND_DATA_MESSAGE: + s->state = STATE_SEND_DATA_END; + s->sendptr = s->textlen = 0; + break; + case STATE_SEND_DATA_END: + s->state = STATE_SEND_QUIT; + s->sendptr = s->textlen = 0; + break; + case STATE_SEND_QUIT: + s->state = STATE_SEND_DONE; + smtp_done(SMTP_ERR_OK); + uip_close(); + break; + } + } +} +/*-----------------------------------------------------------------------------------*/ +static void +newdata(struct smtp_state *s) +{ + if(*(char *)uip_appdata == ISO_5) { + smtp_done(1); + uip_abort(); + return; + } + /* printf("Got %d bytes: '%s'\n", uip_datalen(), + uip_appdata);*/ + switch(s->state) { + case STATE_SEND_NONE: + if(strncmp((char *)uip_appdata, smtp_220, 3) == 0) { + /* printf("Newdata(): SEND_NONE, got 220, towards SEND_HELO\n");*/ + s->state = STATE_SEND_HELO; + s->sendptr = 0; + } + break; + case STATE_SEND_HELO: + if(*(char *)uip_appdata == ISO_2) { + /* printf("Newdata(): SEND_HELO, got 2*, towards SEND_MAIL_FROM\n");*/ + s->state = STATE_SEND_MAIL_FROM; + s->sendptr = 0; + } + break; + case STATE_SEND_MAIL_FROM: + if(*(char *)uip_appdata == ISO_2) { + /* printf("Newdata(): SEND_MAIL_FROM, got 2*, towards SEND_RCPT_TO\n"); */ + /* printf("2\n");*/ + s->state = STATE_SEND_RCPT_TO; + s->textlen = s->sendptr = 0; + } + break; + case STATE_SEND_RCPT_TO: + if(*(char *)uip_appdata == ISO_2) { + /* printf("2\n");*/ + s->state = STATE_SEND_DATA; + s->textlen = s->sendptr = 0; + } + break; + case STATE_SEND_DATA: + if(*(char *)uip_appdata == ISO_3) { + /* printf("3\n");*/ + s->state = STATE_SEND_DATA_HEADERS; + s->textlen = s->sendptr = 0; + } + break; + case STATE_SEND_DATA_HEADERS: + if(*(char *)uip_appdata == ISO_3) { + /* printf("3\n");*/ + s->state = STATE_SEND_DATA_MESSAGE; + s->textlen = s->sendptr = 0; + } + break; + } + +} +/*-----------------------------------------------------------------------------------*/ +void +smtp_appcall(void) +{ + struct smtp_state *s; + + s = (struct smtp_state *)uip_conn->appstate; + + if(uip_connected()) { + /* senddata();*/ + return; + } + if(uip_acked()) { + acked(s); + } + if(uip_newdata()) { + newdata(s); + } + if(uip_rexmit() || + uip_newdata() || + uip_acked()) { + senddata(s); + } else if(uip_poll()) { + senddata(s); + } + /* if(uip_closed()) { + printf("Dnoe\n"); + }*/ + + +} +/*-----------------------------------------------------------------------------------*/ +/** + * Send an e-mail. + * + * \param to The e-mail address of the receiver of the e-mail. + * \param from The e-mail address of the sender of the e-mail. + * \param subject The subject of the e-mail. + * \param msg The actual e-mail message. + * \param msglen The length of the e-mail message. + */ +/*-----------------------------------------------------------------------------------*/ +unsigned char +smtp_send(char *to, char *from, char *subject, + char *msg, u16_t msglen) +{ + struct uip_conn *conn; + struct smtp_state *s; + + conn = uip_connect(smtpserver, HTONS(25)); + if(conn == NULL) { + return 0; + } + s = conn->appstate; + + s->state = STATE_SEND_NONE; + s->sentlen = s->sendptr = s->textlen = 0; + s->to = to; + s->from = from; + s->subject = subject; + s->msg = msg; + s->msglen = msglen; + + return 1; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Specificy an SMTP server and hostname. + * + * This function is used to configure the SMTP module with an SMTP + * server and the hostname of the host. + * + * \param lhostname The hostname of the uIP host. + * + * \param server A pointer to a 4-byte array representing the IP + * address of the SMTP server to be configured. + */ +/*-----------------------------------------------------------------------------------*/ +void +smtp_configure(char *lhostname, u16_t *server) +{ + localhostname = lhostname; + smtpserver[0] = server[0]; + smtpserver[1] = server[1]; +} +/*-----------------------------------------------------------------------------------*/ +/** @} */ diff --git a/unix/uip_arch.h b/apps/smtp/smtp.h similarity index 53% rename from unix/uip_arch.h rename to apps/smtp/smtp.h index ec48bf5..8eae70b 100644 --- a/unix/uip_arch.h +++ b/apps/smtp/smtp.h @@ -1,5 +1,18 @@ + +/** + * \addtogroup smtp + * @{ + */ + + +/** + * \file + * SMTP header file + * \author Adam Dunkels + */ + /* - * Copyright (c) 2001, Adam Dunkels. + * Copyright (c) 2002, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +23,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,23 +41,60 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip_arch.h,v 1.1 2002/01/10 06:22:56 adam Exp $ + * $Id: smtp.h,v 1.1.2.4 2003/10/06 22:56:45 adam Exp $ * */ +#ifndef __SMTP_H__ +#define __SMTP_H__ -#ifndef __UIP_ARCH_H__ -#define __UIP_ARCH_H__ +#include "uipopt.h" -#include "uip.h" +/** + * Error number that signifies a non-error condition. + */ +#define SMTP_ERR_OK 0 -#if UIP_BUFSIZE > 255 -void uip_add_rcv_nxt(u16_t n); -void uip_add_ack_nxt(u16_t n); -#else -void uip_add_rcv_nxt(u8_t n); -void uip_add_ack_nxt(u8_t n); -#endif /* UIP_BUFSIZE > 255 */ -u16_t uip_ipchksum(void); -u16_t uip_tcpchksum(void); +/** + * Callback function that is called when an e-mail transmission is + * done. + * + * This function must be implemented by the module that uses the SMTP + * module. + * + * \param error The number of the error if an error occured, or + * SMTP_ERR_OK. + */ +void smtp_done(unsigned char error); -#endif /* __UIP_ARCH_H__ */ +/* Functions. */ +void smtp_configure(char *localhostname, u16_t *smtpserver); +unsigned char smtp_send(char *to, char *from, + char *subject, char *msg, + u16_t msglen); + +void smtp_appcall(void); + +struct smtp_state { + u8_t state; + char *to; + char *from; + char *subject; + char *msg; + u16_t msglen; + + u16_t sentlen, textlen; + u16_t sendptr; + +}; + + +#ifndef UIP_APPCALL +#define UIP_APPCALL smtp_appcall +#endif + +#ifndef UIP_APPSTATE_SIZE +#define UIP_APPSTATE_SIZE (sizeof(struct smtp_state)) +#endif + + +#endif /* __SMTP_H__ */ diff --git a/apps/telnet/telnet.c b/apps/telnet/telnet.c new file mode 100644 index 0000000..f72b6fc --- /dev/null +++ b/apps/telnet/telnet.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2002, 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: telnet.c,v 1.1.2.3 2003/10/06 11:20:45 adam Exp $ + * + */ + +#include "uip.h" + +#include "telnet.h" + +#ifndef NULL +#define NULL (void *)0 +#endif /* NULL */ + +#define FLAG_CLOSE 1 +#define FLAG_ABORT 2 +/*-----------------------------------------------------------------------------------*/ +unsigned char +telnet_send(struct telnet_state *s, char *text, u16_t len) +{ + if(s->text != NULL) { + return 1; + } + s->text = text; + s->textlen = len; + s->sentlen = 0; + return 0; +} +/*-----------------------------------------------------------------------------------*/ +unsigned char +telnet_close(struct telnet_state *s) +{ + s->flags = FLAG_CLOSE; + if(s->text != NULL) { + return 1; + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +unsigned char +telnet_abort(struct telnet_state *s) +{ + s->flags = FLAG_ABORT; + if(s->text != NULL) { + return 1; + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +static void +acked(struct telnet_state *s) +{ + s->textlen -= s->sentlen; + if(s->textlen == 0) { + s->text = NULL; + telnet_sent(s); + } else { + s->text += s->sentlen; + } + s->sentlen = 0; +} +/*-----------------------------------------------------------------------------------*/ +static void +senddata(struct telnet_state *s) +{ + if(s->text == NULL) { + uip_send(s->text, 0); + return; + } + if(s->textlen > uip_mss()) { + s->sentlen = uip_mss(); + } else { + s->sentlen = s->textlen; + } + uip_send(s->text, s->sentlen); +} +/*-----------------------------------------------------------------------------------*/ +void telnet_app(void) +{ + struct telnet_state *s = (struct telnet_state *)uip_conn->appstate; + + if(uip_connected()) { + s->flags = 0; + telnet_connected(s); + senddata(s); + return; + } + + if(uip_closed()) { + telnet_closed(s); + } + + if(uip_aborted()) { + telnet_aborted(s); + } + if(uip_timedout()) { + telnet_timedout(s); + } + + + if(s->flags & FLAG_CLOSE) { + uip_close(); + return; + } + if(s->flags & FLAG_ABORT) { + uip_abort(); + return; + } + if(uip_acked()) { + acked(s); + } + if(uip_newdata()) { + telnet_newdata(s, (char *)uip_appdata, uip_datalen()); + } + if(uip_rexmit() || + uip_newdata() || + uip_acked()) { + senddata(s); + } else if(uip_poll()) { + senddata(s); + } +} +/*-----------------------------------------------------------------------------------*/ diff --git a/cc65/uip_arch.h b/apps/telnet/telnet.h similarity index 58% rename from cc65/uip_arch.h rename to apps/telnet/telnet.h index 78bb8f7..0d68780 100644 --- a/cc65/uip_arch.h +++ b/apps/telnet/telnet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Adam Dunkels. + * Copyright (c) 2002, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +10,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,23 +28,39 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip_arch.h,v 1.1 2001/11/20 20:49:45 adam Exp $ + * $Id: telnet.h,v 1.1.2.4 2003/10/06 22:56:45 adam Exp $ * */ +#ifndef __TELNET_H__ +#define __TELNET_H__ -#ifndef __UIP_ARCH_H__ -#define __UIP_ARCH_H__ +struct telnet_state { + unsigned char flags; + char *text; + u16_t textlen; + u16_t sentlen; +}; -#include "uip.h" +void telnet_app(void); -#if UIP_BUFSIZE > 255 -void __fastcall__ uip_add_rcv_nxt(u16_t n); -void __fastcall__ uip_add_ack_nxt(u16_t n); -#else -void __fastcall__ uip_add_rcv_nxt(u8_t n); -void __fastcall__ uip_add_ack_nxt(u8_t n); -#endif /* UIP_BUFSIZE > 255 */ -u16_t uip_ipchksum(void); -u16_t uip_tcpchksum(void); +#ifndef UIP_APPCALL +#define UIP_APPCALL telnet_app +#endif -#endif /* __UIP_ARCH_H__ */ +#ifndef UIP_APPSTATE_SIZE +#define UIP_APPSTATE_SIZE (sizeof(struct telnet_state)) +#endif + + +unsigned char telnet_send(struct telnet_state *s, char *text, u16_t len); +unsigned char telnet_close(struct telnet_state *s); +unsigned char telnet_abort(struct telnet_state *s); + +/* Callbacks, must be implemented by the caller. */ +void telnet_connected(struct telnet_state *s); +void telnet_closed(struct telnet_state *s); +void telnet_sent(struct telnet_state *s); +void telnet_aborted(struct telnet_state *s); +void telnet_timedout(struct telnet_state *s); +void telnet_newdata(struct telnet_state *s, char *data, u16_t len); +#endif /* __TELNET_H__ */ diff --git a/apps/telnetd/memb.c b/apps/telnetd/memb.c new file mode 100644 index 0000000..a2079a2 --- /dev/null +++ b/apps/telnetd/memb.c @@ -0,0 +1,152 @@ +/** + * \addtogroup exampleapps + * @{ + */ + +/** + * \file + * Memory block allocation routines. + * \author Adam Dunkels + * + * The memory block allocation routines provide a simple yet powerful + * set of functions for managing a set of memory blocks of fixed + * size. A set of memory blocks is statically declared with the + * MEMB() macro. Memory blocks are allocated from the declared + * memory by the memb_alloc() function, and are deallocated with the + * memb_free() function. + * + * \note Because of namespace clashes only one MEMB() can be + * declared per C module, and the name scope of a MEMB() memory + * block is local to each C module. + * + * The following example shows how to declare and use a memory block + * called "cmem" which has 8 chunks of memory with each memory chunk + * being 20 bytes large. + * + \code + MEMB(cmem, 20, 8); + + int main(int argc, char *argv[]) { + char *ptr; + + memb_init(&cmem); + + ptr = memb_alloc(&cmem); + + if(ptr != NULL) { + do_something(ptr); + } else { + printf("Could not allocate memory.\n"); + } + + if(memb_free(ptr) == 0) { + printf("Deallocation succeeded.\n"); + } + } + \endcode + * + */ + +#include + +#include "memb.h" + +/*------------------------------------------------------------------------------*/ +/** + * Initialize a memory block that was declared with MEMB(). + * + * \param m A memory block previosly declared with MEMB(). + */ +/*------------------------------------------------------------------------------*/ +void +memb_init(struct memb_blocks *m) +{ + memset(m->mem, (m->size + 1) * m->num, 0); +} +/*------------------------------------------------------------------------------*/ +/** + * Allocate a memory block from a block of memory declared with MEMB(). + * + * \param m A memory block previosly declared with MEMB(). + */ +/*------------------------------------------------------------------------------*/ +char * +memb_alloc(struct memb_blocks *m) +{ + int i; + char *ptr; + + ptr = m->mem; + for(i = 0; i < m->num; ++i) { + if(*ptr == 0) { + /* If this block was unused, we increase the reference count to + indicate that it now is used and return a pointer to the + first byte following the reference counter. */ + ++*ptr; + return ptr + 1; + } + ptr += m->size + 1; + } + + /* No free block was found, so we return NULL to indicate failure to + allocate block. */ + return NULL; +} +/*------------------------------------------------------------------------------*/ +/** + * Deallocate a memory block from a memory block previously declared + * with MEMB(). + * + * \param m m A memory block previosly declared with MEMB(). + * + * \param ptr A pointer to the memory block that is to be deallocated. + * + * \return The new reference count for the memory block (should be 0 + * if successfully deallocated) or -1 if the pointer "ptr" did not + * point to a legal memory block. + */ +/*------------------------------------------------------------------------------*/ +char +memb_free(struct memb_blocks *m, char *ptr) +{ + int i; + char *ptr2; + + /* Walk through the list of blocks and try to find the block to + which the pointer "ptr" points to. */ + ptr2 = m->mem; + for(i = 0; i < m->num; ++i) { + + if(ptr2 == ptr - 1) { + /* We've found to block to which "ptr" points so we decrease the + reference count and return the new value of it. */ + return --*ptr2; + } + ptr2 += m->size + 1; + } + return -1; +} +/*------------------------------------------------------------------------------*/ +/** + * Increase the reference count for a memory chunk. + * + * \note No sanity checks are currently made. + * + * \param m m A memory block previosly declared with MEMB(). + * + * \param ptr A pointer to the memory chunk for which the reference + * count should be increased. + * + * \return The new reference count. + */ +/*------------------------------------------------------------------------------*/ +char +memb_ref(struct memb_blocks *m, char *ptr) +{ + return ++*(ptr - 1); +} +/*------------------------------------------------------------------------------*/ + + + + diff --git a/apps/telnetd/memb.h b/apps/telnetd/memb.h new file mode 100644 index 0000000..d073b30 --- /dev/null +++ b/apps/telnetd/memb.h @@ -0,0 +1,43 @@ +/** + * \addtogroup exampleapps + * @{ + */ + +/** + * \file + * Memory block allocation routines. + * \author Adam Dunkels + * + */ + +#ifndef __MEMB_H__ +#define __MEMB_H__ + +/** + * Declare a memory block. + * + * \param name The name of the memory block (later used with + * memb_init(), memb_alloc() and memb_free()). + * + * \param size The size of each memory chunk, in bytes. + * + * \param num The total number of memory chunks in the block. + * + */ +#define MEMB(name, size, num) \ + static char memb_mem[(size + 1) * num]; \ + static struct memb_blocks name = {size, num, memb_mem} + +struct memb_blocks { + unsigned short size; + unsigned short num; + char *mem; +}; + +void memb_init(struct memb_blocks *m); +char *memb_alloc(struct memb_blocks *m); +char memb_ref(struct memb_blocks *m, char *ptr); +char memb_free(struct memb_blocks *m, char *ptr); + + +#endif /* __MEMB_H__ */ diff --git a/apps/telnetd/telnetd-shell.c b/apps/telnetd/telnetd-shell.c new file mode 100644 index 0000000..d5abfb8 --- /dev/null +++ b/apps/telnetd/telnetd-shell.c @@ -0,0 +1,181 @@ +/** + * \addtogroup telnetd + * @{ + */ + +/** + * \file + * An example telnet server shell + * \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. + * + * 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 file is part of the Contiki desktop OS. + * + * $Id: telnetd-shell.c,v 1.1.2.1 2003/10/06 22:56:22 adam Exp $ + * + */ + +#include "uip.h" +#include "telnetd.h" +#include + +struct ptentry { + char c; + void (* pfunc)(struct telnetd_state *s, char *str); +}; + +/*-----------------------------------------------------------------------------------*/ +static void +parse(struct telnetd_state *s, register char *str, struct ptentry *t) +{ + register struct ptentry *p; + char *sstr; + + sstr = str; + + /* Loop over the parse table entries in t in order to find one that + matches the first character in str. */ + for(p = t; p->c != 0; ++p) { + if(*str == p->c) { + /* Skip rest of the characters up to the first space. */ + while(*str != ' ') { + ++str; + } + + /* Skip all spaces.*/ + while(*str == ' ') { + ++str; + } + + /* Call parse table entry function and return. */ + p->pfunc(s, str); + return; + } + } + + /* Did not find matching entry in parse table. We just call the + default handler supplied by the caller and return. */ + p->pfunc(s, str); +} +/*-----------------------------------------------------------------------------------*/ +static void +exitt(struct telnetd_state *s, char *str) +{ + telnetd_close(s); +} +/*-----------------------------------------------------------------------------------*/ +static void +inttostr(register char *str, unsigned int i) +{ + str[0] = '0' + i / 100; + if(str[0] == '0') { + str[0] = ' '; + } + str[1] = '0' + (i / 10) % 10; + if(str[1] == '0') { + str[1] = ' '; + } + str[2] = '0' + i % 10; + str[3] = ' '; + str[4] = 0; +} +/*-----------------------------------------------------------------------------------*/ +static void +stats(struct telnetd_state *s, char *strr) +{ + char str[10]; + + inttostr(str, uip_stat.ip.recv); + telnetd_output(s, "IP packets received ", str); + inttostr(str, uip_stat.ip.sent); + telnetd_output(s, "IP packets sent ", str); + inttostr(str, uip_stat.ip.drop); + telnetd_output(s, "IP packets dropped ", str); + + inttostr(str, uip_stat.icmp.recv); + telnetd_output(s, "ICMP packets received ", str); + inttostr(str, uip_stat.icmp.sent); + telnetd_output(s, "ICMP packets sent ", str); + inttostr(str, uip_stat.icmp.drop); + telnetd_output(s, "ICMP packets dropped ", str); + + inttostr(str, uip_stat.tcp.recv); + telnetd_output(s, "TCP packets received ", str); + inttostr(str, uip_stat.tcp.sent); + telnetd_output(s, "TCP packets sent ", str); + inttostr(str, uip_stat.tcp.drop); + telnetd_output(s, "TCP packets dropped ", str); + inttostr(str, uip_stat.tcp.rexmit); + telnetd_output(s, "TCP packets retransmitted ", str); + inttostr(str, uip_stat.tcp.synrst); + telnetd_output(s, "TCP connection attempts ", str); +} +/*-----------------------------------------------------------------------------------*/ +static void +help(struct telnetd_state *s, char *str) +{ + telnetd_output(s, "Available commands:", ""); + telnetd_output(s, "stats - show uIP statistics", ""); + telnetd_output(s, "exit - exit shell", ""); + telnetd_output(s, "? - show this help", ""); +} +/*-----------------------------------------------------------------------------------*/ +static void +none(struct telnetd_state *s, char *str) +{ + if(strlen(str) > 0) { + telnetd_output(s, "Unknown command", ""); + } +} +/*-----------------------------------------------------------------------------------*/ +static struct ptentry configparsetab[] = + {{'s', stats}, + {'e', exitt}, + {'?', help}, + + /* Default action */ + {0, none}}; +/*-----------------------------------------------------------------------------------*/ +void +telnetd_connected(struct telnetd_state *s) +{ + telnetd_output(s, "uIP command shell", ""); + telnetd_output(s, "Type '?' for help", ""); + telnetd_prompt(s, "uIP-0.9> "); +} +/*-----------------------------------------------------------------------------------*/ +void +telnetd_input(struct telnetd_state *s, char *cmd) +{ + parse(s, cmd, configparsetab); + telnetd_prompt(s, "uIP-0.9> "); +} +/*-----------------------------------------------------------------------------------*/ diff --git a/apps/telnetd/telnetd.c b/apps/telnetd/telnetd.c new file mode 100644 index 0000000..9c7e49e --- /dev/null +++ b/apps/telnetd/telnetd.c @@ -0,0 +1,392 @@ +/** + * \addtogroup exampleapps + * @{ + */ + +/** + * \defgroup telnetd Telnet server + * @{ + * + * The uIP telnet server provides a command based interface to uIP. It + * allows using the "telnet" application to access uIP, and implements + * the required telnet option negotiation. + * + * The code is structured in a way which makes it possible to add + * commands without having to rewrite the main telnet code. The main + * telnet code calls two callback functions, telnetd_connected() and + * telnetd_input(), when a telnet connection has been established and + * when a line of text arrives on a telnet connection. These two + * functions can be implemented in a way which suits the particular + * application or environment in which the uIP system is intended to + * be run. + * + * The uIP distribution contains an example telnet shell + * implementation that provides a basic set of commands. + */ + +/** + * \file + * Implementation of the Telnet server. + * \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. + * + * 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 file is part of the uIP TCP/IP stack. + * + * $Id: telnetd.c,v 1.1.2.2 2003/10/07 13:47:50 adam Exp $ + * + */ + +#include "uip.h" +#include "memb.h" +#include "telnetd.h" +#include + +#define ISO_nl 0x0a +#define ISO_cr 0x0d + +MEMB(linemem, TELNETD_LINELEN, TELNETD_NUMLINES); + +static u8_t i; + +#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 +/*-----------------------------------------------------------------------------------*/ +static char * +alloc_line(void) +{ + return memb_alloc(&linemem); +} +/*-----------------------------------------------------------------------------------*/ +static void +dealloc_line(char *line) +{ + memb_free(&linemem, line); +} +/*-----------------------------------------------------------------------------------*/ +static void +sendline(struct telnetd_state *s, char *line) +{ + static unsigned int i; + for(i = 0; i < TELNETD_NUMLINES; ++i) { + if(s->lines[i] == NULL) { + s->lines[i] = line; + break; + } + } + if(i == TELNETD_NUMLINES) { + dealloc_line(line); + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Close a telnet session. + * + * This function can be called from a telnet command in order to close + * the connection. + * + * \param s The connection which is to be closed. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +telnetd_close(struct telnetd_state *s) +{ + s->state = STATE_CLOSE; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Print a prompt on a telnet connection. + * + * This function can be called by the telnet command shell in order to + * print out a command prompt. + * + * \param s A telnet connection. + * + * \param str The command prompt. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +telnetd_prompt(struct telnetd_state *s, char *str) +{ + char *line; + line = alloc_line(); + if(line != NULL) { + strncpy(line, str, TELNETD_LINELEN); + sendline(s, line); + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Print out a string on a telnet connection. + * + * This function can be called from a telnet command parser in order + * to print out a string of text on the connection. The two strings + * given as arguments to the function will be concatenated, a carrige + * return and a new line character will be added, and the line is + * sent. + * + * \param s The telnet connection. + * + * \param str1 The first string. + * + * \param str2 The second string. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +telnetd_output(struct telnetd_state *s, char *str1, char *str2) +{ + static unsigned len; + char *line; + + line = alloc_line(); + if(line != NULL) { + len = strlen(str1); + strncpy(line, str1, TELNETD_LINELEN); + if(len < TELNETD_LINELEN) { + strncpy(line + len, str2, TELNETD_LINELEN - len); + } + len = strlen(line); + if(len < TELNETD_LINELEN - 2) { + line[len] = ISO_cr; + line[len+1] = ISO_nl; + line[len+2] = 0; + } + sendline(s, line); + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Initialize the telnet server. + * + * This function will perform the necessary initializations and start + * listening on TCP port 23. + */ +/*-----------------------------------------------------------------------------------*/ +void +telnetd_init(void) +{ + memb_init(&linemem); + uip_listen(HTONS(23)); +} +/*-----------------------------------------------------------------------------------*/ +static void +acked(struct telnetd_state *s) +{ + dealloc_line(s->lines[0]); + for(i = 1; i < TELNETD_NUMLINES; ++i) { + s->lines[i - 1] = s->lines[i]; + } +} +/*-----------------------------------------------------------------------------------*/ +static void +senddata(struct telnetd_state *s) +{ + if(s->lines[0] != NULL) { + uip_send(s->lines[0], strlen(s->lines[0])); + } +} +/*-----------------------------------------------------------------------------------*/ +static void +getchar(struct telnetd_state *s, u8_t c) +{ + if(c == ISO_cr) { + return; + } + + s->buf[(int)s->bufptr] = c; + if(s->buf[(int)s->bufptr] == ISO_nl || + s->bufptr == sizeof(s->buf) - 1) { + if(s->bufptr > 0) { + s->buf[(int)s->bufptr] = 0; + } + telnetd_input(s, s->buf); + s->bufptr = 0; + } else { + ++s->bufptr; + } +} +/*-----------------------------------------------------------------------------------*/ +static void +sendopt(struct telnetd_state *s, u8_t option, u8_t value) +{ + char *line; + line = alloc_line(); + if(line != NULL) { + line[0] = TELNET_IAC; + line[1] = option; + line[2] = value; + line[3] = 0; + sendline(s, line); + } +} +/*-----------------------------------------------------------------------------------*/ +static void +newdata(struct telnetd_state *s) +{ + u16_t len; + u8_t c; + + + len = uip_datalen(); + + while(len > 0 && s->bufptr < sizeof(s->buf)) { + c = *uip_appdata; + ++uip_appdata; + --len; + switch(s->state) { + case STATE_IAC: + if(c == TELNET_IAC) { + getchar(s, c); + s->state = STATE_NORMAL; + } else { + switch(c) { + case TELNET_WILL: + s->state = STATE_WILL; + break; + case TELNET_WONT: + s->state = STATE_WONT; + break; + case TELNET_DO: + s->state = STATE_DO; + break; + case TELNET_DONT: + s->state = STATE_DONT; + break; + default: + s->state = STATE_NORMAL; + break; + } + } + break; + case STATE_WILL: + /* Reply with a DONT */ + sendopt(s, TELNET_DONT, c); + s->state = STATE_NORMAL; + break; + + case STATE_WONT: + /* Reply with a DONT */ + sendopt(s, TELNET_DONT, c); + s->state = STATE_NORMAL; + break; + case STATE_DO: + /* Reply with a WONT */ + sendopt(s, TELNET_WONT, c); + s->state = STATE_NORMAL; + break; + case STATE_DONT: + /* Reply with a WONT */ + sendopt(s, TELNET_WONT, c); + s->state = STATE_NORMAL; + break; + case STATE_NORMAL: + if(c == TELNET_IAC) { + s->state = STATE_IAC; + } else { + getchar(s, c); + } + break; + } + + + } + +} +/*-----------------------------------------------------------------------------------*/ +void +telnetd_app(void) +{ + struct telnetd_state *s; + + s = (struct telnetd_state *)uip_conn->appstate; + + if(uip_connected()) { + + for(i = 0; i < TELNETD_NUMLINES; ++i) { + s->lines[i] = NULL; + } + s->bufptr = 0; + s->state = STATE_NORMAL; + + telnetd_connected(s); + senddata(s); + return; + } + + if(s->state == STATE_CLOSE) { + s->state = STATE_NORMAL; + uip_close(); + return; + } + + if(uip_closed()) { + telnetd_output(s, "Connection closed", ""); + } + + + if(uip_aborted()) { + telnetd_output(s, "Connection reset", ""); + } + + if(uip_timedout()) { + telnetd_output(s, "Connection timed out", ""); + } + + if(uip_acked()) { + acked(s); + } + + if(uip_newdata()) { + newdata(s); + } + + if(uip_rexmit() || + uip_newdata() || + uip_acked()) { + senddata(s); + } else if(uip_poll()) { + senddata(s); + } +} +/*-----------------------------------------------------------------------------------*/ diff --git a/apps/telnetd/telnetd.h b/apps/telnetd/telnetd.h new file mode 100644 index 0000000..9f292cf --- /dev/null +++ b/apps/telnetd/telnetd.h @@ -0,0 +1,114 @@ +/** + * \addtogroup telnetd + * @{ + */ + +/** + * \file + * Header file for the telnet server. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2002, 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: telnetd.h,v 1.1.2.2 2003/10/07 13:22:27 adam Exp $ + * + */ +#ifndef __TELNETD_H__ +#define __TELNETD_H__ + +#include "uip.h" + +/** + * The maximum length of a telnet line. + * + * \hideinitializer + */ +#define TELNETD_LINELEN 36 + +/** + * The number of output lines being buffered for all telnet + * connections. + * + * \hideinitializer + */ +#define TELNETD_NUMLINES 24 + +/** + * A telnet connection structure. + */ +struct telnetd_state { + char *lines[TELNETD_NUMLINES]; + char buf[TELNETD_LINELEN]; + char bufptr; + u8_t state; +}; + + +/** + * Callback function that is called when a telnet connection has been + * established. + * + * \param s The telnet connection. + */ +void telnetd_connected(struct telnetd_state *s); + +/** + * Callback function that is called when a line of text has arrived on + * a telnet connection. + * + * \param s The telnet connection. + * + * \param cmd The line of text. + */ +void telnetd_input(struct telnetd_state *s, char *cmd); + + +void telnetd_close(struct telnetd_state *s); +void telnetd_output(struct telnetd_state *s, char *s1, char *s2); +void telnetd_prompt(struct telnetd_state *s, char *str); + +void telnetd_app(void); + +#ifndef UIP_APPCALL +#define UIP_APPCALL telnetd_app +#endif + +#ifndef UIP_APPSTATE_SIZE +#define UIP_APPSTATE_SIZE (sizeof(struct telnetd_state)) +#endif + +void telnetd_init(void); + + +#endif /* __TELNET_H__ */ + +/** @} */ diff --git a/apps/webclient/http-strings b/apps/webclient/http-strings new file mode 100644 index 0000000..8710354 --- /dev/null +++ b/apps/webclient/http-strings @@ -0,0 +1,12 @@ +http_200 "200 " +http_301 "301 " +http_302 "302 " +http_get "GET " +http_10 "HTTP/1.0" +http_11 "HTTP/1.1" +http_content_type "Content-Type: " +http_texthtml "text/html" +http_location "Location: " +http_host "Host: " +http_connection_close "Connection: close" +http_user_agent "User-Agent: Contiki/1.0 (Commodore 64; http://dunkels.com/adam/contiki/)" diff --git a/apps/webclient/http-strings.c b/apps/webclient/http-strings.c new file mode 100644 index 0000000..b5afbbc --- /dev/null +++ b/apps/webclient/http-strings.c @@ -0,0 +1,39 @@ +char http_200[5] = +/* 200 */ +{0x32, 0x30, 0x30, 0x20, }; +char http_301[5] = +/* 301 */ +{0x33, 0x30, 0x31, 0x20, }; +char http_302[5] = +/* 302 */ +{0x33, 0x30, 0x32, 0x20, }; +char http_get[5] = +/* GET */ +{0x47, 0x45, 0x54, 0x20, }; +char http_10[9] = +/* HTTP/1.0 */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, }; +char http_11[9] = +/* HTTP/1.1 */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, }; +char http_content_type[15] = +/* Content-Type: */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, }; +char http_texthtml[10] = +/* text/html */ +{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, }; +char http_location[11] = +/* Location: */ +{0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, }; +char http_host[7] = +/* Host: */ +{0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, }; +char http_connection_close[18] = +/* Connection: close */ +{0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, }; +char http_user_agent[73] = +/* User-Agent: Contiki/1.0 (Commodore 64; http://dunkels.com/adam/contiki/) */ +{0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6b, 0x69, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x28, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x6f, 0x72, 0x65, 0x20, 0x36, 0x34, 0x3b, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6b, 0x69, 0x2f, 0x29, }; +char test_httpstring[16] = +/* HTTP/1.0 200 OK */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, }; diff --git a/apps/webclient/http-strings.h b/apps/webclient/http-strings.h new file mode 100644 index 0000000..8a49c32 --- /dev/null +++ b/apps/webclient/http-strings.h @@ -0,0 +1,13 @@ +extern char http_200[5]; +extern char http_301[5]; +extern char http_302[5]; +extern char http_get[5]; +extern char http_10[9]; +extern char http_11[9]; +extern char http_content_type[15]; +extern char http_texthtml[10]; +extern char http_location[11]; +extern char http_host[7]; +extern char http_connection_close[18]; +extern char http_user_agent[73]; +extern char test_httpstring[16]; diff --git a/apps/webclient/makehttpstrings b/apps/webclient/makehttpstrings new file mode 100755 index 0000000..b39d6ac --- /dev/null +++ b/apps/webclient/makehttpstrings @@ -0,0 +1,27 @@ +#!/usr/bin/perl + +open(OUTPUTC, "> http-strings.c"); +open(OUTPUTH, "> http-strings.h"); + +open(FILE, "http-strings"); + +while() { + if(/(.+) "(.+)"/) { + $var = $1; + $data = $2; + + printf(OUTPUTC "char $var\[%d] = \n", length($data) + 1); + printf(OUTPUTC "/* $data */\n"); + printf(OUTPUTC "{"); + for($j = 0; $j < length($data); $j++) { + printf(OUTPUTC "%#02x, ", unpack("C", substr($data, $j, 1))); + } + printf(OUTPUTC "};\n"); + + printf(OUTPUTH "extern char $var\[%d];\n", length($data) + 1); + + } +} +exit 0; + +printf(OUTPUT "%#02x, ", unpack("C", $data)); diff --git a/apps/webclient/webclient.c b/apps/webclient/webclient.c new file mode 100644 index 0000000..ae04a9e --- /dev/null +++ b/apps/webclient/webclient.c @@ -0,0 +1,460 @@ +/** + * \addtogroup exampleapps + * @{ + */ + +/** + * \defgroup webclient Web client + * @{ + * + * This example shows a HTTP client that is able to download web pages + * and files from web servers. It requires a number of callback + * functions to be implemented by the module that utilizes the code: + * webclient_datahandler(), webclient_connected(), + * webclient_timedout(), webclient_aborted(), webclient_closed(). + */ + +/** + * \file + * Implementation of the HTTP client. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2002, 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. + * + * This file is part of the "contiki" web browser. + * + * $Id: webclient.c,v 1.1.2.5 2003/10/06 22:56:45 adam Exp $ + * + */ + +#include "uip.h" +#include "webclient.h" +#include "resolv.h" + +#include + +#define WEBCLIENT_TIMEOUT 100 + +#define WEBCLIENT_STATE_STATUSLINE 0 +#define WEBCLIENT_STATE_HEADERS 1 +#define WEBCLIENT_STATE_DATA 2 +#define WEBCLIENT_STATE_CLOSE 3 + +#define HTTPFLAG_NONE 0 +#define HTTPFLAG_OK 1 +#define HTTPFLAG_MOVED 2 +#define HTTPFLAG_ERROR 3 + + +#define ISO_nl 0x0a +#define ISO_cr 0x0d +#define ISO_space 0x20 + +struct webclient_state { + u8_t timer; + u8_t state; + u8_t httpflag; + + u16_t port; + char host[40]; + char file[WWW_CONF_MAX_URLLEN]; + u16_t getrequestptr; + u16_t getrequestleft; + + char httpheaderline[200]; + u16_t httpheaderlineptr; + + char mimetype[32]; +}; + +static struct webclient_state s; + +/*-----------------------------------------------------------------------------------*/ +char * +webclient_mimetype(void) +{ + return s.mimetype; +} +/*-----------------------------------------------------------------------------------*/ +char * +webclient_filename(void) +{ + return s.file; +} +/*-----------------------------------------------------------------------------------*/ +char * +webclient_hostname(void) +{ + return s.host; +} +/*-----------------------------------------------------------------------------------*/ +unsigned short +webclient_port(void) +{ + return s.port; +} +/*-----------------------------------------------------------------------------------*/ +void +webclient_init(void) +{ + +} +/*-----------------------------------------------------------------------------------*/ +static void +init_connection(void) +{ + s.state = WEBCLIENT_STATE_STATUSLINE; + + s.getrequestleft = sizeof(http_get) - 1 + 1 + + sizeof(http_10) - 1 + + sizeof(http_crnl) - 1 + + sizeof(http_host) - 1 + + sizeof(http_crnl) - 1 + + strlen(http_user_agent_fields) + + strlen(s.file) + strlen(s.host); + s.getrequestptr = 0; + + s.httpheaderlineptr = 0; +} +/*-----------------------------------------------------------------------------------*/ +void +webclient_close(void) +{ + s.state = WEBCLIENT_STATE_CLOSE; +} +/*-----------------------------------------------------------------------------------*/ +unsigned char +webclient_get(char *host, u16_t port, char *file) +{ + struct uip_conn *conn; + u16_t *ipaddr; + static u16_t addr[2]; + + /* First check if the host is an IP address. */ + ipaddr = &addr[0]; + if(uip_main_ipaddrconv(host, (unsigned char *)addr) == 0) { + ipaddr = resolv_lookup(host); + + if(ipaddr == NULL) { + return 0; + } + } + + conn = uip_connect(ipaddr, htons(port)); + + if(conn == NULL) { + return 0; + } + + s.port = port; + strncpy(s.file, file, sizeof(s.file)); + strncpy(s.host, host, sizeof(s.host)); + + init_connection(); + return 1; +} +/*-----------------------------------------------------------------------------------*/ +static unsigned char * CC_FASTCALL +copy_string(unsigned char *dest, + const unsigned char *src, unsigned char len) +{ + return strcpy(dest, src) + len; +} +/*-----------------------------------------------------------------------------------*/ +static void +senddata(void) +{ + u16_t len; + char *getrequest; + char *cptr; + + if(s.getrequestleft > 0) { + cptr = getrequest = (char *)uip_appdata; + + cptr = copy_string(cptr, http_get, sizeof(http_get) - 1); + cptr = copy_string(cptr, s.file, strlen(s.file)); + *cptr++ = ISO_space; + cptr = copy_string(cptr, http_10, sizeof(http_10) - 1); + + cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1); + + cptr = copy_string(cptr, http_host, sizeof(http_host) - 1); + cptr = copy_string(cptr, s.host, strlen(s.host)); + cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1); + + cptr = copy_string(cptr, http_user_agent_fields, + strlen(http_user_agent_fields)); + + len = s.getrequestleft > uip_mss()? + uip_mss(): + s.getrequestleft; + uip_send(&(getrequest[s.getrequestptr]), len); + } +} +/*-----------------------------------------------------------------------------------*/ +static void +acked(void) +{ + u16_t len; + + if(s.getrequestleft > 0) { + len = s.getrequestleft > uip_mss()? + uip_mss(): + s.getrequestleft; + s.getrequestleft -= len; + s.getrequestptr += len; + } +} +/*-----------------------------------------------------------------------------------*/ +static u16_t +parse_statusline(u16_t len) +{ + char *cptr; + + while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) { + s.httpheaderline[s.httpheaderlineptr] = *uip_appdata; + ++uip_appdata; + --len; + if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) { + + if((strncmp(s.httpheaderline, http_10, + sizeof(http_10) - 1) == 0) || + (strncmp(s.httpheaderline, http_11, + sizeof(http_11) - 1) == 0)) { + cptr = &(s.httpheaderline[9]); + s.httpflag = HTTPFLAG_NONE; + if(strncmp(cptr, http_200, sizeof(http_200) - 1) == 0) { + /* 200 OK */ + s.httpflag = HTTPFLAG_OK; + } else if(strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 || + strncmp(cptr, http_302, sizeof(http_302) - 1) == 0) { + /* 301 Moved permanently or 302 Found. Location: header line + will contain thw new location. */ + s.httpflag = HTTPFLAG_MOVED; + } else { + s.httpheaderline[s.httpheaderlineptr - 1] = 0; + } + } else { + uip_abort(); + webclient_aborted(); + return 0; + } + + /* We're done parsing the status line, so we reset the pointer + and start parsing the HTTP headers.*/ + s.httpheaderlineptr = 0; + s.state = WEBCLIENT_STATE_HEADERS; + break; + } else { + ++s.httpheaderlineptr; + } + } + return len; +} +/*-----------------------------------------------------------------------------------*/ +static char +casecmp(char *str1, const char *str2, char len) +{ + static char c; + + while(len > 0) { + c = *str1; + /* Force lower-case characters. */ + if(c & 0x40) { + c |= 0x20; + } + if(*str2 != c) { + return 1; + } + ++str1; + ++str2; + --len; + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +static u16_t +parse_headers(u16_t len) +{ + char *cptr; + static unsigned char i; + + while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) { + s.httpheaderline[s.httpheaderlineptr] = *uip_appdata; + ++uip_appdata; + --len; + if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) { + /* We have an entire HTTP header line in s.httpheaderline, so + we parse it. */ + if(s.httpheaderline[0] == ISO_cr) { + /* This was the last header line (i.e., and empty "\r\n"), so + we are done with the headers and proceed with the actual + data. */ + s.state = WEBCLIENT_STATE_DATA; + return len; + } + + s.httpheaderline[s.httpheaderlineptr - 1] = 0; + /* Check for specific HTTP header fields. */ + if(casecmp(s.httpheaderline, http_content_type, + sizeof(http_content_type) - 1) == 0) { + /* Found Content-type field. */ + cptr = strchr(s.httpheaderline, ';'); + if(cptr != NULL) { + *cptr = 0; + } + strncpy(s.mimetype, s.httpheaderline + + sizeof(http_content_type) - 1, sizeof(s.mimetype)); + } else if(casecmp(s.httpheaderline, http_location, + sizeof(http_location) - 1) == 0) { + cptr = s.httpheaderline + + sizeof(http_location) - 1; + + if(strncmp(cptr, http_http, 7) == 0) { + cptr += 7; + for(i = 0; i < s.httpheaderlineptr - 7; ++i) { + if(*cptr == 0 || + *cptr == '/' || + *cptr == ' ' || + *cptr == ':') { + s.host[i] = 0; + break; + } + s.host[i] = *cptr; + ++cptr; + } + } + strncpy(s.file, cptr, sizeof(s.file)); + /* s.file[s.httpheaderlineptr - i] = 0;*/ + } + + + /* We're done parsing, so we reset the pointer and start the + next line. */ + s.httpheaderlineptr = 0; + } else { + ++s.httpheaderlineptr; + } + } + return len; +} +/*-----------------------------------------------------------------------------------*/ +static void +newdata(void) +{ + u16_t len; + + len = uip_datalen(); + + if(s.state == WEBCLIENT_STATE_STATUSLINE) { + len = parse_statusline(len); + } + + if(s.state == WEBCLIENT_STATE_HEADERS && len > 0) { + len = parse_headers(len); + } + + if(len > 0 && s.state == WEBCLIENT_STATE_DATA && + s.httpflag != HTTPFLAG_MOVED) { + webclient_datahandler((char *)uip_appdata, len); + } +} +/*-----------------------------------------------------------------------------------*/ +void webclient_appcall(void) +{ + if(uip_connected()) { + s.timer = 0; + s.state = WEBCLIENT_STATE_STATUSLINE; + senddata(); + webclient_connected(); + return; + } + + + if(state == NULL) { + uip_abort(); + return; + } + + if(s.state == WEBCLIENT_STATE_CLOSE) { + webclient_closed(); + uip_abort(); + return; + } + + + + if(uip_aborted()) { + webclient_aborted(); + } + if(uip_timedout()) { + webclient_timedout(); + } + + + if(uip_acked()) { + s.timer = 0; + acked(); + } + if(uip_newdata()) { + s.timer = 0; + newdata(); + } + if(uip_rexmit() || + uip_newdata() || + uip_acked()) { + senddata(); + } else if(uip_poll()) { + ++s.timer; + if(s.timer == WEBCLIENT_TIMEOUT) { + webclient_timedout(); + uip_abort(); + return; + } + /* senddata();*/ + } + + if(uip_closed()) { + if(s.httpflag != HTTPFLAG_MOVED) { + /* Send NULL data to signal EOF. */ + webclient_datahandler(NULL, 0); + } else { + if(resolv_lookup(s.host) == NULL) { + resolv_query(s.host); + } + webclient_get(s.host, s.port, s.file); + } + } +} +/*-----------------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ diff --git a/apps/webclient/webclient.h b/apps/webclient/webclient.h new file mode 100644 index 0000000..9ec2686 --- /dev/null +++ b/apps/webclient/webclient.h @@ -0,0 +1,207 @@ +/** + * \addtogroup webclient + * @{ + */ + +/** + * \file + * Header file for the HTTP client. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2002, 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. + * + * This file is part of the "contiki" web browser. + * + * $Id: webclient.h,v 1.1.2.5 2003/10/06 22:56:45 adam Exp $ + * + */ +#ifndef __WEBCLIENT_H__ +#define __WEBCLIENT_H__ + + +#include "http-strings.h" +#include "http-user-agent-string.h" + + +struct webclient_state; + +/** + * Callback function that is called from the webclient code when HTTP + * data has been received. + * + * This function must be implemented by the module that uses the + * webclient code. The function is called from the webclient module + * when HTTP data has been received. The function is not called when + * HTTP headers are received, only for the actual data. + * + * \note This function is called many times, repetedly, when data is + * being received, and not once when all data has been received. + * + * \param data A pointer to the data that has been received. + * \param len The length of the data that has been received. + */ +void webclient_datahandler(char *data, u16_t len); + +/** + * Callback function that is called from the webclient code when the + * HTTP connection has been connected to the web server. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_connected(void); + +/** + * Callback function that is called from the webclient code if the + * HTTP connection to the web server has timed out. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_timedout(void); + +/** + * Callback function that is called from the webclient code if the + * HTTP connection to the web server has been aborted by the web + * server. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_aborted(void); + +/** + * Callback function that is called from the webclient code when the + * HTTP connection to the web server has been closed. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_closed(void); + + + +/** + * Initialize the webclient module. + */ +void webclient_init(void); + +/** + * Open an HTTP connection to a web server and ask for a file using + * the GET method. + * + * This function opens an HTTP connection to the specified web server + * and requests the specified file using the GET method. When the HTTP + * connection has been connected, the webclient_connected() callback + * function is called and when the HTTP data arrives the + * webclient_datahandler() callback function is called. + * + * The callback function webclient_timedout() is called if the web + * server could not be contacted, and the webclient_aborted() callback + * function is called if the HTTP connection is aborted by the web + * server. + * + * When the HTTP request has been completed and the HTTP connection is + * closed, the webclient_closed() callback function will be called. + * + * \note If the function is passed a host name, it must already be in + * the resolver cache in order for the function to connect to the web + * server. It is therefore up to the calling module to implement the + * resolver calls and the signal handler used for reporting a resolv + * query answer. + * + * \param host A pointer to a string containing either a host name or + * a numerical IP address in dotted decimal notation (e.g., 192.168.23.1). + * + * \param port The port number to which to connect, in host byte order. + * + * \param file A pointer to the name of the file to get. + * + * \retval 0 if the host name could not be found in the cache, or + * if a TCP connection could not be created. + * + * \retval 1 if the connection was initiated. + */ +unsigned char webclient_get(char *host, u16_t port, char *file); + +/** + * Close the currently open HTTP connection. + */ +void webclient_close(void); +void webclient_appcall(void); + +/** + * Obtain the MIME type of the current HTTP data stream. + * + * \return A pointer to a string contaning the MIME type. The string + * may be empty if no MIME type was reported by the web server. + */ +char *webclient_mimetype(void); + +/** + * Obtain the filename of the current HTTP data stream. + * + * The filename of an HTTP request may be changed by the web server, + * and may therefore not be the same as when the original GET request + * was made with webclient_get(). This function is used for obtaining + * the current filename. + * + * \return A pointer to the current filename. + */ +char *webclient_filename(void); + +/** + * Obtain the hostname of the current HTTP data stream. + * + * The hostname of the web server of an HTTP request may be changed + * by the web server, and may therefore not be the same as when the + * original GET request was made with webclient_get(). This function + * is used for obtaining the current hostname. + * + * \return A pointer to the current hostname. + */ +char *webclient_hostname(void); + +/** + * Obtain the port number of the current HTTP data stream. + * + * The port number of an HTTP request may be changed by the web + * server, and may therefore not be the same as when the original GET + * request was made with webclient_get(). This function is used for + * obtaining the current port number. + * + * \return The port number of the current HTTP data stream, in host byte order. + */ +unsigned short webclient_port(void); + +#endif /* __WEBCLIENT_H__ */ + +/** @} */ diff --git a/cc65/Makefile b/cc65/Makefile deleted file mode 100644 index f9b8f88..0000000 --- a/cc65/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by Adam Dunkels. -# 4. 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. -# -# This file is part of the uIP TCP/IP stack. -# -# $Id: Makefile,v 1.2 2001/11/24 16:03:59 adam Exp $ -# - -# Change the target system type here -SYS=c64 - -CC=cc65 -AS=ca65 -AR=ar65 -ARFLAGS=a -CFLAGS= -I ../uip -I ../apps/httpd -t $(SYS) -Oi - -%.o: - $(CC) $(CFLAGS) -o $(patsubst %c, %s, $(notdir $<)) $< - $(AS) -o $@ $(AFLAGS) $(*).s - -uip: uip.o uip_arch.o rs232dev.o main.o httpd.o fs.o cgi.o - cl65 -o uip -t $(SYS) $^ - - -tunslip: tunslip.c - gcc -o tunslip tunslip.c - -rs232dev.o: rs232dev.c ../uip/uip.h uipopt.h -main.o: main.c ../uip/uip.h uipopt.h \ - rs232dev.h -uip.o: ../uip/uip.c uipopt.h -httpd.o: ../apps/httpd/httpd.c ../apps/httpd/httpd.h ../uip/uip.h uipopt.h \ - ../apps/httpd/fs.c ../apps/httpd/fs.h \ - ../apps/httpd/fsdata.c ../apps/httpd/fsdata.h -cgi.o: ../apps/httpd/cgi.c ../apps/httpd/cgi.h -fs.o: ../apps/httpd/fs.c ../apps/httpd/fs.h ../apps/httpd/fsdata.c -uip_arch.o: uip_arch.c uip_arch.h ../uip/uip.h uipopt.h \ - ../apps/httpd/httpd.h - - -clean: - rm -f *.o *~ *core uip *.s diff --git a/cc65/README b/cc65/README deleted file mode 100644 index 13f8aae..0000000 --- a/cc65/README +++ /dev/null @@ -1,5 +0,0 @@ -This directory is a port of uIP to the popular Commodore 64 home -computer. In order to compile it, you need the cc65 C compiler that -can be downloaded from . - -The "tunslip" executable can be used on a FreeBSD system to create a virtual SLIP interface between the kernel and the Vice emulator. diff --git a/cc65/slipdev.c b/cc65/slipdev.c deleted file mode 100644 index 5cf85be..0000000 --- a/cc65/slipdev.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. 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. - * - * This file is part of the uIP TCP/IP stack. - * - * $Id: slipdev.c,v 1.1 2001/11/20 20:49:45 adam Exp $ - * - */ - - -#include "uip.h" - -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 - - -#define SIO_RECV(c) while(rs232_get(&c) == RS_ERR_NO_DATA) -#define SIO_SEND(c) while(rs232_put(c) == RS_ERR_OVERFLOW) - -#define MAX_SIZE UIP_BUFSIZE - -static const unsigned char slip_end = SLIP_END, - slip_esc = SLIP_ESC, - slip_esc_end = SLIP_ESC_END, - slip_esc_esc = SLIP_ESC_ESC; - -/*-----------------------------------------------------------------------------------*/ -void -slipdev_send(void) -{ - u8_t i; - u8_t *ptr; - u8_t c; - - SIO_SEND(slip_end); - - ptr = uip_buf; - for(i = 0; i < uip_len; i++) { - c = *ptr++; - switch(c) { - case SLIP_END: - SIO_SEND(slip_esc); - SIO_SEND(slip_esc_end); - break; - case SLIP_ESC: - SIO_SEND(slip_esc); - SIO_SEND(slip_esc_esc); - break; - default: - SIO_SEND(c); - break; - } - } - SIO_SEND(slip_end); -} -/*-----------------------------------------------------------------------------------*/ -u8_t -slipdev_read(void) -{ - u8_t c; - - start: - uip_len = 0; - while(1) { - if(uip_len >= MAX_SIZE) { - goto start; - } - SIO_RECV(c); - switch(c) { - case SLIP_END: - if(uip_len > 0) { - return uip_len; - } else { - goto start; - } - break; - case SLIP_ESC: - SIO_RECV(c); - switch(c) { - case SLIP_ESC_END: - c = SLIP_END; - break; - case SLIP_ESC_ESC: - c = SLIP_ESC; - break; - } - /* FALLTHROUGH */ - default: - if(uip_len < MAX_SIZE) { - uip_buf[uip_len] = c; - uip_len++; - } - break; - } - - } - return 0; -} -/*-----------------------------------------------------------------------------------*/ -void -slipdev_init(void) -{ -} -/*-----------------------------------------------------------------------------------*/ - - - - - - - diff --git a/cc65/tunslip.c b/cc65/tunslip.c deleted file mode 100644 index 7aed724..0000000 --- a/cc65/tunslip.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. 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. - * - * This file is part of the uIP TCP/IP stack. - * - * $Id: tunslip.c,v 1.1 2001/11/20 20:49:45 adam Exp $ - * - */ - - -#include -#include -#include -#include -#include - -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 - -/*-----------------------------------------------------------------------------------*/ -void -do_slip(int infd, int outfd) -{ - static unsigned char inbuf[2000]; - static int inbufptr = 0; - unsigned char c; - - if(read(infd, &c, 1) == -1) { - perror("do_slip: read"); - } - fprintf(stderr, "."); - switch(c) { - case SLIP_END: - if(inbufptr > 0) { - if(write(outfd, inbuf, inbufptr) == -1) { - perror("do_slip: write"); - } - inbufptr = 0; - } - return; - case SLIP_ESC: - if(read(infd, &c, 1) == -1) { - perror("do_slip: read after esc"); - } - switch(c) { - case SLIP_ESC_END: - c = SLIP_END; - break; - case SLIP_ESC_ESC: - c = SLIP_ESC; - break; - } - /* FALLTHROUGH */ - default: - inbuf[inbufptr++] = c; - break; - } -} -/*-----------------------------------------------------------------------------------*/ -void -slip_send(int outfd, unsigned char data) -{ - unsigned char d; - - d = data; - write(outfd, &d, 1); -} -/*-----------------------------------------------------------------------------------*/ -void -do_tun(int infd, int outfd) -{ - unsigned char inbuf[2000]; - int i, size; - - if((size = read(infd, inbuf, 2000)) == -1) { - perror("do_tun: read"); - } - - for(i = 0; i < size; i++) { - switch(inbuf[i]) { - case SLIP_END: - slip_send(outfd, SLIP_ESC); - slip_send(outfd, SLIP_ESC_END); - break; - case SLIP_ESC: - slip_send(outfd, SLIP_ESC); - slip_send(outfd, SLIP_ESC_ESC); - break; - default: - slip_send(outfd, inbuf[i]); - break; - } - - } - slip_send(outfd, SLIP_END); -} -/*-----------------------------------------------------------------------------------*/ -int -main(int argc, char **argv) -{ - int tunfd, infd, outfd, maxfd; - int ret; - fd_set fdset; - - infd = STDIN_FILENO; - outfd = STDOUT_FILENO; - - fprintf(stderr, "tunslip started...\n"); - tunfd = open("/dev/tun0", O_RDWR); - if(tunfd == -1) { - perror("main: open"); - exit(1); - } - fprintf(stderr, "opened device...\n"); -#ifdef linux - system("ifconfig tun0 inet 192.168.0.2 192.168.0.1"); - - system("route add -net 192.168.0.0 netmask 255.255.255.0 dev tun0"); -#else - /* system("ifconfig tun0 inet sidewalker rallarsnus"); */ - system("ifconfig tun0 inet 192.168.0.1 192.168.0.2"); -#endif /* linux */ - - fprintf(stderr, "configured interface...\n"); - - while(1) { - maxfd = 0; - FD_ZERO(&fdset); - FD_SET(infd, &fdset); - if(infd > maxfd) maxfd = infd; - - FD_SET(outfd, &fdset); - if(outfd > maxfd) maxfd = outfd; - - FD_SET(tunfd, &fdset); - if(tunfd > maxfd) maxfd = tunfd; - - ret = select(maxfd + 1, &fdset, NULL, NULL, NULL); - if(ret == -1) { - perror("select"); - exit(0); - } else if(ret > 0) { - if(FD_ISSET(infd, &fdset)) { - do_slip(infd, tunfd); - } else if(FD_ISSET(tunfd, &fdset)) { - do_tun(tunfd, outfd); - } else { - exit(0); - } - } else { - exit(0); - } - } - -} -/*-----------------------------------------------------------------------------------*/ diff --git a/cc65/uip_arch.c b/cc65/uip_arch.c deleted file mode 100644 index af2b58c..0000000 --- a/cc65/uip_arch.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. 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. - * - * This file is part of the uIP TCP/IP stack. - * - * $Id: uip_arch.c,v 1.1 2001/11/20 20:49:45 adam Exp $ - * - */ - - -#include "uip_arch.h" -#include "uip.h" - -/* This is assembler versions of the uIP support functions for the - 6502 CPU. Note that the checksum function ("_chksum()", defined - under uip_ipchksum()) does not support buffer sizes > 255 bytes. */ - -/*-----------------------------------------------------------------------------------*/ -static u16_t chksum_ptr, chksum_len, chksum_tmp; -static u16_t chksum(void); -/*-----------------------------------------------------------------------------------*/ -u16_t -uip_ipchksum(void) -{ - chksum_ptr = (u16_t)uip_buf; - chksum_len = 20; - return chksum(); -} -/*asm("__chksum:");*/ -u16_t chksum(void) { -asm("lda #0"); -asm("sta tmp1"); -asm("sta tmp1+1"); -asm("lda _chksum_ptr"); -asm("sta ptr1"); -asm("lda _chksum_ptr+1"); -asm("sta ptr1+1"); -asm("lda _chksum_len"); -asm("lsr"); -asm("bcc chksum_noodd"); -asm("pha"); -asm("ldy _chksum_len"); -asm("dey"); -asm("lda (ptr1),y"); -asm("sta tmp1"); -asm("pla"); -asm("chksum_noodd:"); -asm("asl"); -asm("tay"); -asm("clc"); -asm("php"); -asm("chksum_loop1:"); -asm("cpy #0"); -asm("beq chksum_loop1_end"); -asm("plp"); -asm("dey"); -asm("dey"); -asm("lda (ptr1),y"); -asm("adc tmp1"); -asm("sta tmp1"); -asm("iny"); -asm("lda (ptr1),y"); -asm("adc tmp1+1"); -asm("sta tmp1+1"); -asm("dey"); -asm("php"); -asm("jmp chksum_loop1"); -asm("chksum_loop1_end:"); -asm("plp"); -asm("chksum_endloop:"); -asm("lda tmp1"); -asm("adc #0"); -asm("sta tmp1"); -asm("lda tmp1+1"); -asm("adc #0"); -asm("sta tmp1+1"); -asm("bcs chksum_endloop"); -asm("lda tmp1"); -asm("ldx tmp1+1"); -asm("rts"); -} -/*-----------------------------------------------------------------------------------*/ -u16_t -uip_tcpchksum(void) -{ - chksum_ptr = (u16_t)&uip_buf[20]; - chksum_len = 20; - chksum_tmp = chksum(); - - chksum_ptr = (u16_t)uip_appdata; - asm("lda _uip_buf+3"); - asm("sec"); - asm("sbc #40"); - asm("sta _chksum_len"); - /* asm("lda _uip_buf+2"); - asm("sbc #0");*/ - asm("lda #0"); - asm("sta _chksum_len+1"); - asm("jsr %v", chksum); - - asm("clc"); - asm("adc _chksum_tmp"); - asm("sta _chksum_tmp"); - asm("txa"); - asm("adc _chksum_tmp+1"); - asm("sta _chksum_tmp+1"); - - asm("tcpchksum_loop1:"); - asm("lda _chksum_tmp"); - asm("adc #0"); - asm("sta _chksum_tmp"); - asm("lda _chksum_tmp+1"); - asm("adc #0"); - asm("sta _chksum_tmp+1"); - asm("bcs tcpchksum_loop1"); - - - asm("lda _uip_buf+3"); - asm("sec"); - asm("sbc #20"); - asm("sta _chksum_len"); - asm("lda _uip_buf+2"); - asm("sbc #0"); - asm("sta _chksum_len+1"); - - - asm("ldy #$0c"); - asm("clc"); - asm("php"); - asm("tcpchksum_loop2:"); - asm("plp"); - asm("lda _uip_buf,y"); - asm("adc _chksum_tmp"); - asm("sta _chksum_tmp"); - asm("iny"); - asm("lda _uip_buf,y"); - asm("adc _chksum_tmp+1"); - asm("sta _chksum_tmp+1"); - asm("iny"); - asm("php"); - asm("cpy #$14"); - asm("bne tcpchksum_loop2"); - - asm("plp"); - - asm("lda _chksum_tmp"); - asm("adc #0"); - asm("sta _chksum_tmp"); - asm("lda _chksum_tmp+1"); - asm("adc #6"); /* IP_PROTO_TCP */ - asm("sta _chksum_tmp+1"); - - - asm("lda _chksum_tmp"); - asm("adc _chksum_len+1"); - asm("sta _chksum_tmp"); - asm("lda _chksum_tmp+1"); - asm("adc _chksum_len"); - asm("sta _chksum_tmp+1"); - - - - asm("tcpchksum_loop3:"); - asm("lda _chksum_tmp"); - asm("adc #0"); - asm("sta _chksum_tmp"); - asm("lda _chksum_tmp+1"); - asm("adc #0"); - asm("sta _chksum_tmp+1"); - asm("bcs tcpchksum_loop3"); - - - return chksum_tmp; -} -/*-----------------------------------------------------------------------------------*/ -/*void -uip_add_rcv_nxt(u8_t n) -{ - uip_conn->rcv_nxt[3] += n; - if(uip_conn->rcv_nxt[3] < n) { - uip_conn->rcv_nxt[2]++; - if(uip_conn->rcv_nxt[2] == 0) { - uip_conn->rcv_nxt[1]++; - if(uip_conn->rcv_nxt[1] == 0) { - uip_conn->rcv_nxt[0]++; - } - } - } -}*/ -void __fastcall__ -uip_add_rcv_nxt(u8_t n) { - /*asm("_uip_add_rcv_nxt:");*/ - asm("pha"); - asm("lda _uip_conn"); - asm("sta ptr1"); - asm("lda _uip_conn+1"); - asm("sta ptr1+1"); - asm("pla"); - asm("clc"); - asm("ldy #12"); - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - asm("dey"); -#if UIP_BUFSIZE > 255 - asm("txa"); -#else - asm("lda #0"); -#endif /* UIP_BUFSIZE > 255 */ - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - asm("dey"); - asm("lda #0"); - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - asm("dey"); - asm("lda #0"); - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - /*asm("rts"); - asm(".export _uip_add_rcv_nxt");*/ -} -/*-----------------------------------------------------------------------------------*/ -/*void -uip_add_ack_nxt(u8_t n) -{ - uip_conn->ack_nxt[3] += n; - if(uip_conn->ack_nxt[3] < n) { - uip_conn->ack_nxt[2]++; - if(uip_conn->ack_nxt[2] == 0) { - uip_conn->ack_nxt[1]++; - if(uip_conn->ack_nxt[1] == 0) { - uip_conn->ack_nxt[0]++; - } - } - } -}*/ -void __fastcall__ -uip_add_ack_nxt(u8_t n) { - /*asm("_uip_add_ack_nxt:");*/ - asm("pha"); - asm("lda _uip_conn"); - asm("sta ptr1"); - asm("lda _uip_conn+1"); - asm("sta ptr1+1"); - asm("pla"); - asm("clc"); - asm("ldy #20"); - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - asm("dey"); -#if UIP_BUFSIZE > 255 - asm("txa"); -#else - asm("lda #0"); -#endif /* UIP_BUFSIZE > 255 */ - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - asm("dey"); - asm("lda #0"); - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - asm("dey"); - asm("lda #0"); - asm("adc (ptr1),y"); - asm("sta (ptr1),y"); - /*asm("rts"); - asm(".export _uip_add_ack_nxt");*/ -} -/*-----------------------------------------------------------------------------------*/ - - diff --git a/cc65/uipopt.h b/cc65/uipopt.h deleted file mode 100644 index 8eda8eb..0000000 --- a/cc65/uipopt.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. 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. - * - * This file is part of the uIP TCP/IP stack. - * - * $Id: uipopt.h,v 1.6 2002/01/11 12:43:14 adam Exp $ - * - */ - -#ifndef __UIPOPT_H__ -#define __UIPOPT_H__ - -/* This file is used for tweaking various configuration options for - uIP. You should make a copy of this file into one of your project's - directories instead of editing this example "uipopt.h" file that - comes with the uIP distribution. */ - -/*-----------------------------------------------------------------------------------*/ -/* First, two typedefs that may have to be tweaked for your particular - compiler. The uX_t types are unsigned integer types, where the X is - the number of bits in the integer type. Most compilers use - "unsigned char" and "unsigned short" for those two, - respectively. */ -typedef unsigned char u8_t; -typedef unsigned short u16_t; - -/*-----------------------------------------------------------------------------------*/ -/* The configuration options for a specific node. This includes IP - * address, netmask and default router as well as the Ethernet - * address. The netmask, default router and Ethernet address are - * appliciable only if uIP should be run over Ethernet. - * - * All of these should be changed to suit your project. -*/ - -/* UIP_IPADDR: The IP address of this uIP node. */ -#define UIP_IPADDR0 192 -#define UIP_IPADDR1 168 -#define UIP_IPADDR2 0 -#define UIP_IPADDR3 2 - -/* UIP_NETMASK: The netmask. */ -#define UIP_NETMASK0 255 -#define UIP_NETMASK1 255 -#define UIP_NETMASK2 255 -#define UIP_NETMASK3 0 - -/* UIP_DRIPADDR: IP address of the default router. */ -#define UIP_DRIPADDR0 192 -#define UIP_DRIPADDR1 168 -#define UIP_DRIPADDR2 0 -#define UIP_DRIPADDR3 1 - -/* UIP_ETHADDR: The Ethernet address. */ -#define UIP_ETHADDR0 0x00 -#define UIP_ETHADDR1 0xbd -#define UIP_ETHADDR2 0x3b -#define UIP_ETHADDR3 0x33 -#define UIP_ETHADDR4 0x05 -#define UIP_ETHADDR5 0x71 - - -/*-----------------------------------------------------------------------------------*/ -/* The following options are used to configure application specific - * setting such as how many TCP ports that should be avaliable and if - * the uIP should be configured to support active opens. - * - * These should probably be tweaked to suite your project. - */ - -/* Include the header file for the application program that should be - used. If you don't use the example web server, you should change - this. */ -#include "httpd.h" - -/* UIP_CONNS: The maximum number of simultaneously active - connections. */ -#define UIP_CONNS 10 - -/* UIP_LISTENPORTS: The maximum number of simultaneously listening TCP - ports. */ -#define UIP_LISTENPORTS 1 - -/* UIP_ACTIVE_OPEN: Determines if support for opening connections from - uIP should be compiled in. If this isn't needed for your - application, don't turn it on. (A web server doesn't need this, for - instance.) */ -#define UIP_ACTIVE_OPEN 0 - -/* UIP_BUFSIZE: The size of the buffer that holds incoming and - outgoing packets. */ -#define UIP_BUFSIZE 160 - -/* UIP_STATISTICS: Determines if statistics support should be compiled - in. The statistics is useful for debugging and to show the user. */ -#define UIP_STATISTICS 1 - -/* UIP_LOGGING: Determines if logging of certain events should be - compiled in. Useful mostly for debugging. The function uip_log(char - *msg) must be implemented to suit your architecture if logging is - turned on. */ -#define UIP_LOGGING 0 - -/* UIP_LLH_LEN: The link level header length; this is the offset into - the uip_buf where the IP header can be found. For Ethernet, this - should be set to 14. For SLIP, this should be set to 0. */ -#define UIP_LLH_LEN 0 - -/*-----------------------------------------------------------------------------------*/ -/* The following configuration options can be tweaked for your - * project, but you are probably safe to use the default values. The - * options are listed in order of importance. - */ - -/* UIP_MAXRTX: The maximum number of times a segment should be - retransmitted before the connection should be aborted. */ -#define UIP_MAXRTX 8 - -/* UIP_ARPTAB_SIZE: The size of the ARP table - use a larger value if - this uIP node will have many connections from the local network. */ -#define UIP_ARPTAB_SIZE 8 - -/* The maxium age of ARP table entries measured in 10ths of - seconds. An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD - default). */ -#define UIP_ARP_MAXAGE 120 - -/* UIP_RTO: The retransmission timeout counted in timer pulses (i.e., - the speed of the periodic timer, usually one second). */ -#define UIP_RTO 3 - -/* UIP_TCP_MSS: The TCP maximum segment size. This should be set to - at most UIP_BUFSIZE - UIP_LLH_LEN - 40. */ -#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40) - -/* UIP_TTL: The IP TTL (time to live) of IP packets sent by uIP. */ -#define UIP_TTL 255 - -/* UIP_TIME_WAIT_TIMEOUT: How long a connection should stay in the - TIME_WAIT state. Has no real implication, so it should be left - untouched. */ -#define UIP_TIME_WAIT_TIMEOUT 120 -/*-----------------------------------------------------------------------------------*/ -/* This is where you configure if your CPU architecture is big or - * little endian. Most CPUs today are little endian. The most notable - * exception are the Motorolas which are big endian. Tweak the - * definition of the BYTE_ORDER macro to configure uIP for your - * project. - */ -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 3412 -#endif /* LITTLE_ENDIAN */ -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 1234 -#endif /* BIGE_ENDIAN */ - -#ifndef BYTE_ORDER -#define BYTE_ORDER LITTLE_ENDIAN -#endif /* BYTE_ORDER */ - -#endif /* __UIPOPT_H__ */ diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..d1c00fb --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,234 @@ +# Doxyfile 1.3.3 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "uIP 0.9" +PROJECT_NUMBER = +OUTPUT_DIRECTORY = . +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = ../ \ + ../../ +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +SHORT_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = NO +GENERATE_DEPRECATEDLIST= NO +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = uip-doc.txt \ + ../uip/uip.h \ + ../uip/uip.c \ + ../uip/uip_arch.h \ + ../uip/uip_arp.h \ + ../uip/uip_arp.c \ + ../uip/slipdev.h \ + ../uip/slipdev.c \ + ../unix/uipopt.h \ + ../apps/webclient/webclient.h \ + ../apps/webclient/webclient.c \ + ../apps/smtp/smtp.h \ + ../apps/smtp/smtp.c \ + ../apps/telnetd/telnetd.h \ + ../apps/telnetd/telnetd.c \ + ../apps/telnetd/telnetd-shell.c \ + ../apps/telnetd/memb.h \ + ../apps/telnetd/memb.c \ + ../apps/httpd/httpd.h \ + ../apps/httpd/httpd.c \ + ../apps/httpd/cgi.h \ + ../apps/httpd/cgi.c \ + ../apps/httpd/fs.h \ + ../apps/httpd/fs.c \ + ../apps/resolv/resolv.h \ + ../apps/resolv/resolv.c +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = YES +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = YES +BINARY_TOC = YES +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = UIP_UDP +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = NO +COLLABORATION_GRAPH = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = search.cgi +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = /usr/local/bin/ +EXT_DOC_PATHS = diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..fadaea6 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,5 @@ +htmldoc: + doxygen Doxyfile + +pdfdoc: htmldoc + cd latex; make refman.pdf && mv refman.pdf ../uip-refman.pdf \ No newline at end of file diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..3a65aef --- /dev/null +++ b/doc/README @@ -0,0 +1,12 @@ +The files in this directory comprise the uIP documentation. The files +are: + +html/ The uIP reference manual in HTML format. + +uip-refman.pdf The uIP reference manual in a printable PDF version. + +mobisys2003.pdf Conference paper about uIP from the First + International Conference on Mobile Systems, + Applications and Services (MobiSys), San + Francisco, May 2003. + diff --git a/doc/html/a00030.html b/doc/html/a00030.html new file mode 100644 index 0000000..725cf12 --- /dev/null +++ b/doc/html/a00030.html @@ -0,0 +1,33 @@ + + +uIP 0.9: fs_file struct Reference + + + + +

    fs_file Struct Reference
    + +[Web server] +

    #include <fs.h> +

    +


    Detailed Description

    +An open file in the read-only file system. +

    + + + + + + + + + +

    Data Fields

    +char * data
     The actual file data.

    +int len
     The length of the file data.

    +


    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00036.html b/doc/html/a00036.html new file mode 100644 index 0000000..ea1329f --- /dev/null +++ b/doc/html/a00036.html @@ -0,0 +1,24 @@ + + +uIP 0.9: telnetd_state struct Reference + + + + +

    telnetd_state Struct Reference
    + +[Telnet server] +

    #include <telnetd.h> +

    +


    Detailed Description

    +A telnet connection structure. +

    + + +
    +


    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00037.html b/doc/html/a00037.html new file mode 100644 index 0000000..ede2947 --- /dev/null +++ b/doc/html/a00037.html @@ -0,0 +1,87 @@ + + +uIP 0.9: uip_conn struct Reference + + + + +

    uip_conn Struct Reference
    + +[The uIP TCP/IP stack] +

    #include <uip.h> +

    +


    Detailed Description

    +Representation of a uIP TCP connection. +

    +The uip_conn structure is used for identifying a connection. All but one field in the structure are to be considered read-only by an application. The only exception is the appstate field whos purpose is to let the application store application-specific state (e.g., file pointers) for the connection. The size of this field is configured in the "uipopt.h" header file. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Data Fields

    +u16_t ripaddr [2]
     The IP address of the remote host.

    +u16_t lport
     The local TCP port, in network byte order.

    +u16_t rport
     The local remote TCP port, in network byte order.

    +u8_t rcv_nxt [4]
     The sequence number that we expect to receive next.

    +u8_t snd_nxt [4]
     The sequence number that was last sent by us.

    +u16_t len
     Length of the data that was previously sent.

    +u16_t mss
     Current maximum segment size for the connection.

    +u16_t initialmss
     Initial maximum segment size for the connection.

    +u8_t sa
     Retransmission time-out calculation state variable.

    +u8_t sv
     Retransmission time-out calculation state variable.

    +u8_t rto
     Retransmission time-out.

    +u8_t tcpstateflags
     TCP state and flags.

    +u8_t timer
     The retransmission timer.

    +u8_t nrtx
     The number of retransmissions for the last segment sent.

    +u8_t appstate [UIP_APPSTATE_SIZE]
     The application state.

    +


    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00038.html b/doc/html/a00038.html new file mode 100644 index 0000000..a8dba05 --- /dev/null +++ b/doc/html/a00038.html @@ -0,0 +1,24 @@ + + +uIP 0.9: uip_eth_addr struct Reference + + + + +

    uip_eth_addr Struct Reference
    + +[uIP Address Resolution Protocol] +

    #include <uip_arp.h> +

    +


    Detailed Description

    +Representation of a 48-bit Ethernet address. +

    + + +
    +


    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00039.html b/doc/html/a00039.html new file mode 100644 index 0000000..f8d5c0f --- /dev/null +++ b/doc/html/a00039.html @@ -0,0 +1,28 @@ + + +uIP 0.9: uip_eth_hdr struct Reference + + + + +

    uip_eth_hdr Struct Reference
    + +[uIP Address Resolution Protocol] +

    #include <uip_arp.h> +

    +Collaboration diagram for uip_eth_hdr:

    Collaboration graph
    + + + +
    [legend]

    Detailed Description

    +The Ethernet header. +

    + + +
    +


    Generated on Tue Oct 7 15:51:42 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00041.html b/doc/html/a00041.html new file mode 100644 index 0000000..3afba21 --- /dev/null +++ b/doc/html/a00041.html @@ -0,0 +1,448 @@ + + +uIP 0.9: uip_stats struct Reference + + + + +

    uip_stats Struct Reference
    + +[The uIP TCP/IP stack] +

    #include <uip.h> +

    +


    Detailed Description

    +The structure holding the TCP/IP statistics that are gathered if UIP_STATISTICS is set to 1. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Data Fields

    +struct {
       uip_stats_t   drop
       uip_stats_t   recv
       uip_stats_t   sent
       uip_stats_t   vhlerr
       uip_stats_t   hblenerr
       uip_stats_t   lblenerr
       uip_stats_t   fragerr
       uip_stats_t   chkerr
       uip_stats_t   protoerr
    ip
     IP statistics.

    +struct {
       uip_stats_t   drop
       uip_stats_t   recv
       uip_stats_t   sent
       uip_stats_t   typeerr
    icmp
     ICMP statistics.

    +struct {
       uip_stats_t   drop
       uip_stats_t   recv
       uip_stats_t   sent
       uip_stats_t   chkerr
       uip_stats_t   ackerr
       uip_stats_t   rst
       uip_stats_t   rexmit
       uip_stats_t   syndrop
       uip_stats_t   synrst
    tcp
     TCP statistics.

    +


    Field Documentation

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::ackerr +
    +
    + + + + + +
    +   + + +

    +Number of TCP segments with a bad ACK number. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::chkerr +
    +
    + + + + + +
    +   + + +

    +Number of TCP segments with a bad checksum. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::drop +
    +
    + + + + + +
    +   + + +

    +Number of dropped TCP segments. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::fragerr +
    +
    + + + + + +
    +   + + +

    +Number of packets dropped since they were IP fragments. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::hblenerr +
    +
    + + + + + +
    +   + + +

    +Number of packets dropped due to wrong IP length, high byte. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::lblenerr +
    +
    + + + + + +
    +   + + +

    +Number of packets dropped due to wrong IP length, low byte. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::protoerr +
    +
    + + + + + +
    +   + + +

    +Number of packets dropped since they were neither ICMP, UDP nor TCP. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::recv +
    +
    + + + + + +
    +   + + +

    +Number of recived TCP segments. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::rexmit +
    +
    + + + + + +
    +   + + +

    +Number of retransmitted TCP segments. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::rst +
    +
    + + + + + +
    +   + + +

    +Number of recevied TCP RST (reset) segments. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::sent +
    +
    + + + + + +
    +   + + +

    +Number of sent TCP segments. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::syndrop +
    +
    + + + + + +
    +   + + +

    +Number of dropped SYNs due to too few connections was avaliable. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::synrst +
    +
    + + + + + +
    +   + + +

    +Number of SYNs for closed ports, triggering a RST. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::typeerr +
    +
    + + + + + +
    +   + + +

    +Number of ICMP packets with a wrong type. +

    +

    +

    + + + + +
    + + +
    uip_stats_t uip_stats::vhlerr +
    +
    + + + + + +
    +   + + +

    +Number of packets dropped due to wrong IP version or header length. +

    +

    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00046.html b/doc/html/a00046.html new file mode 100644 index 0000000..21a22e3 --- /dev/null +++ b/doc/html/a00046.html @@ -0,0 +1,37 @@ + + +uIP 0.9: uip_udp_conn struct Reference + + + + +

    uip_udp_conn Struct Reference
    + +[The uIP TCP/IP stack] +

    #include <uip.h> +

    +


    Detailed Description

    +Representation of a uIP UDP connection. +

    + + + + + + + + + + + + +

    Data Fields

    +u16_t ripaddr [2]
     The IP address of the remote peer.

    +u16_t lport
     The local port number in network byte order.

    +u16_t rport
     The remote port number in network byte order.

    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00049.html b/doc/html/a00049.html new file mode 100644 index 0000000..bd9dea0 --- /dev/null +++ b/doc/html/a00049.html @@ -0,0 +1,43 @@ + + +uIP 0.9: cgi.c File Reference + + + + +

    apps/httpd/cgi.c File Reference


    Detailed Description

    +HTTP server script language C functions file. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    +This file contains functions that are called by the web server scripts. The functions takes one argument, and the return value is interpreted as follows. A zero means that the function did not complete and should be invoked for the next packet as well. A non-zero value indicates that the function has completed and that the web server should move along to the next script line. +

    +#include "uip.h"
    +#include "cgi.h"
    +#include "httpd.h"
    +#include "fs.h"
    +#include <stdio.h>
    +#include <string.h>
    + +

    +Include dependency graph for cgi.c:

    Include dependency graph
    + + + + + + + + + + + + + +

    Variables

    +cgifunction cgitab []
     A table containing pointers to C functions that can be called from a web server script.

    +
    Generated on Tue Oct 7 15:51:03 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00050.html b/doc/html/a00050.html new file mode 100644 index 0000000..fddbfc4 --- /dev/null +++ b/doc/html/a00050.html @@ -0,0 +1,34 @@ + + +uIP 0.9: cgi.h File Reference + + + + +

    apps/httpd/cgi.h File Reference


    Detailed Description

    +HTTP script language header file. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + +

    Variables

    +cgifunction cgitab []
     A table containing pointers to C functions that can be called from a web server script.

    +
    Generated on Tue Oct 7 15:51:04 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00051.html b/doc/html/a00051.html new file mode 100644 index 0000000..a1dc71c --- /dev/null +++ b/doc/html/a00051.html @@ -0,0 +1,44 @@ + + +uIP 0.9: fs.c File Reference + + + + +

    apps/httpd/fs.c File Reference


    Detailed Description

    +HTTP server read-only file system code. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    +A simple read-only filesystem. +

    +#include "uip.h"
    +#include "httpd.h"
    +#include "fs.h"
    +#include "fsdata.h"
    +#include "fsdata.c"
    + +

    +Include dependency graph for fs.c:

    Include dependency graph
    + + + + + + + + + + + + + + + +

    Functions

    int fs_open (const char *name, struct fs_file *file)
     Open a file in the read-only file system.

    +void fs_init (void)
     Initialize the read-only file system.

    +
    Generated on Tue Oct 7 15:51:05 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00052.html b/doc/html/a00052.html new file mode 100644 index 0000000..9482628 --- /dev/null +++ b/doc/html/a00052.html @@ -0,0 +1,51 @@ + + +uIP 0.9: fs.h File Reference + + + + +

    apps/httpd/fs.h File Reference


    Detailed Description

    +HTTP server read-only file system header file. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    + +

    +Include dependency graph for fs.h:

    Include dependency graph
    + + + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + +

    Data Structures

    struct  fs_file
     An open file in the read-only file system. More...


    Functions

    int fs_open (const char *name, struct fs_file *file)
     Open a file in the read-only file system.

    +void fs_init (void)
     Initialize the read-only file system.

    +
    Generated on Tue Oct 7 15:51:07 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00053.html b/doc/html/a00053.html new file mode 100644 index 0000000..b9951cc --- /dev/null +++ b/doc/html/a00053.html @@ -0,0 +1,41 @@ + + +uIP 0.9: httpd.c File Reference + + + + +

    apps/httpd/httpd.c File Reference


    Detailed Description

    +HTTP server. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    +#include "httpd.h"
    +#include "fs.h"
    +#include "fsdata.h"
    +#include "cgi.h"
    + +

    +Include dependency graph for httpd.c:

    Include dependency graph
    + + + + + + + + + + + + + +

    Functions

    void httpd_init (void)
     Initialize the web server.

    +
    Generated on Tue Oct 7 15:51:07 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00054.html b/doc/html/a00054.html new file mode 100644 index 0000000..a0ee8cd --- /dev/null +++ b/doc/html/a00054.html @@ -0,0 +1,38 @@ + + +uIP 0.9: httpd.h File Reference + + + + +

    apps/httpd/httpd.h File Reference


    Detailed Description

    +HTTP server header file. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + +

    Functions

    void httpd_init (void)
     Initialize the web server.

    +
    Generated on Tue Oct 7 15:51:09 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00055.html b/doc/html/a00055.html new file mode 100644 index 0000000..a3e2037 --- /dev/null +++ b/doc/html/a00055.html @@ -0,0 +1,50 @@ + + +uIP 0.9: resolv.c File Reference + + + + +

    apps/resolv/resolv.c File Reference


    Detailed Description

    +DNS host name to IP address resolver. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    +This file implements a DNS host name to IP address resolver. +

    +#include "resolv.h"
    +#include <string.h>
    + +

    +Include dependency graph for resolv.c:

    Include dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    void resolv_query (char *name)
     Queues a name so that a question for the name will be sent out.

    u16_tresolv_lookup (char *name)
     Look up a hostname in the array of known hostnames.

    u16_tresolv_getserver (void)
     Obtain the currently configured DNS server.

    void resolv_conf (u16_t *dnsserver)
     Configure which DNS server to use for queries.

    +void resolv_init (void)
     Initalize the resolver.

    +
    Generated on Tue Oct 7 15:51:09 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00056.html b/doc/html/a00056.html new file mode 100644 index 0000000..eb1c2b3 --- /dev/null +++ b/doc/html/a00056.html @@ -0,0 +1,58 @@ + + +uIP 0.9: resolv.h File Reference + + + + +

    apps/resolv/resolv.h File Reference


    Detailed Description

    +DNS resolver code header file. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    + +

    +Include dependency graph for resolv.h:

    Include dependency graph
    + + + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    void resolv_found (char *name, u16_t *ipaddr)
     Callback function which is called when a hostname is found.

    void resolv_conf (u16_t *dnsserver)
     Configure which DNS server to use for queries.

    u16_tresolv_getserver (void)
     Obtain the currently configured DNS server.

    +void resolv_init (void)
     Initalize the resolver.

    u16_tresolv_lookup (char *name)
     Look up a hostname in the array of known hostnames.

    void resolv_query (char *name)
     Queues a name so that a question for the name will be sent out.

    +
    Generated on Tue Oct 7 15:51:11 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00057.html b/doc/html/a00057.html new file mode 100644 index 0000000..022aed2 --- /dev/null +++ b/doc/html/a00057.html @@ -0,0 +1,42 @@ + + +uIP 0.9: smtp.c File Reference + + + + +

    apps/smtp/smtp.c File Reference


    Detailed Description

    +SMTP example implementation. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    +#include "smtp.h"
    +#include "smtp-strings.h"
    +#include <string.h>
    + +

    +Include dependency graph for smtp.c:

    Include dependency graph
    + + + + + + + + + + + + + + + +

    Functions

    unsigned char smtp_send (char *to, char *from, char *subject, char *msg, u16_t msglen)
     Send an e-mail.

    void smtp_configure (char *lhostname, u16_t *server)
     Specificy an SMTP server and hostname.

    +
    Generated on Tue Oct 7 15:51:12 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00058.html b/doc/html/a00058.html new file mode 100644 index 0000000..f617cc1 --- /dev/null +++ b/doc/html/a00058.html @@ -0,0 +1,59 @@ + + +uIP 0.9: smtp.h File Reference + + + + +

    apps/smtp/smtp.h File Reference


    Detailed Description

    +SMTP header file. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uipopt.h"
    + +

    +Include dependency graph for smtp.h:

    Include dependency graph
    + + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    +#define SMTP_ERR_OK   0
     Error number that signifies a non-error condition.

    +#define UIP_APPCALL   smtp_appcall
     The name of the application function that uIP should call in response to TCP/IP events.

    +#define UIP_APPSTATE_SIZE   (sizeof(struct smtp_state))
     The size of the application state that is to be stored in the uip_conn structure.


    Functions

    void smtp_done (unsigned char error)
     Callback function that is called when an e-mail transmission is done.

    void smtp_configure (char *localhostname, u16_t *smtpserver)
     Specificy an SMTP server and hostname.

    unsigned char smtp_send (char *to, char *from, char *subject, char *msg, u16_t msglen)
     Send an e-mail.

    +
    Generated on Tue Oct 7 15:51:14 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00059.html b/doc/html/a00059.html new file mode 100644 index 0000000..292bc97 --- /dev/null +++ b/doc/html/a00059.html @@ -0,0 +1,65 @@ + + +uIP 0.9: memb.c File Reference + + + + +

    apps/telnetd/memb.c File Reference


    Detailed Description

    +Memory block allocation routines. +

    +

    Author:
    Adam Dunkels <adam@sics.se>
    +The memory block allocation routines provide a simple yet powerful set of functions for managing a set of memory blocks of fixed size. A set of memory blocks is statically declared with the MEMB() macro. Memory blocks are allocated from the declared memory by the memb_alloc() function, and are deallocated with the memb_free() function.

    +

    Note:
    Because of namespace clashes only one MEMB() can be declared per C module, and the name scope of a MEMB() memory block is local to each C module.
    +The following example shows how to declare and use a memory block called "cmem" which has 8 chunks of memory with each memory chunk being 20 bytes large.

    +

     MEMB(cmem, 20, 8);
    +
    + int main(int argc, char *argv[]) {
    +    char *ptr;
    +    
    +    memb_init(&cmem);
    +
    +    ptr = memb_alloc(&cmem);
    +
    +    if(ptr != NULL) {
    +       do_something(ptr);
    +    } else {
    +       printf("Could not allocate memory.\n");
    +    }
    +
    +    if(memb_free(ptr) == 0) {
    +       printf("Deallocation succeeded.\n");
    +    }
    + }
    +
    +

    +#include <string.h>
    +#include "memb.h"
    + +

    +Include dependency graph for memb.c:

    Include dependency graph
    + + + + + + + + + + + + + + + + + + +

    Functions

    void memb_init (struct memb_blocks *m)
     Initialize a memory block that was declared with MEMB().

    char * memb_alloc (struct memb_blocks *m)
     Allocate a memory block from a block of memory declared with MEMB().

    char memb_free (struct memb_blocks *m, char *ptr)
     Deallocate a memory block from a memory block previously declared with MEMB().

    char memb_ref (struct memb_blocks *m, char *ptr)
     Increase the reference count for a memory chunk.

    +
    Generated on Tue Oct 7 15:51:14 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00060.html b/doc/html/a00060.html new file mode 100644 index 0000000..d0941c3 --- /dev/null +++ b/doc/html/a00060.html @@ -0,0 +1,46 @@ + + +uIP 0.9: memb.h File Reference + + + + +

    apps/telnetd/memb.h File Reference


    Detailed Description

    +Memory block allocation routines. +

    +

    Author:
    Adam Dunkels <adam@sics.se>
    + +

    + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    #define MEMB(name, size, num)
     Declare a memory block.


    Functions

    void memb_init (struct memb_blocks *m)
     Initialize a memory block that was declared with MEMB().

    char * memb_alloc (struct memb_blocks *m)
     Allocate a memory block from a block of memory declared with MEMB().

    char memb_ref (struct memb_blocks *m, char *ptr)
     Increase the reference count for a memory chunk.

    char memb_free (struct memb_blocks *m, char *ptr)
     Deallocate a memory block from a memory block previously declared with MEMB().

    +
    Generated on Tue Oct 7 15:51:15 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00061.html b/doc/html/a00061.html new file mode 100644 index 0000000..1eb004b --- /dev/null +++ b/doc/html/a00061.html @@ -0,0 +1,41 @@ + + +uIP 0.9: telnetd-shell.c File Reference + + + + +

    apps/telnetd/telnetd-shell.c File Reference


    Detailed Description

    +An example telnet server shell. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    +#include "telnetd.h"
    +#include <string.h>
    + +

    +Include dependency graph for telnetd-shell.c:

    Include dependency graph
    + + + + + + + + + + + + + + + +

    Functions

    void telnetd_connected (struct telnetd_state *s)
     Callback function that is called when a telnet connection has been established.

    void telnetd_input (struct telnetd_state *s, char *cmd)
     Callback function that is called when a line of text has arrived on a telnet connection.

    +
    Generated on Tue Oct 7 15:51:16 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00062.html b/doc/html/a00062.html new file mode 100644 index 0000000..254217b --- /dev/null +++ b/doc/html/a00062.html @@ -0,0 +1,49 @@ + + +uIP 0.9: telnetd.c File Reference + + + + +

    apps/telnetd/telnetd.c File Reference


    Detailed Description

    +Implementation of the Telnet server. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    +#include "memb.h"
    +#include "telnetd.h"
    +#include <string.h>
    + +

    +Include dependency graph for telnetd.c:

    Include dependency graph
    + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    void telnetd_close (struct telnetd_state *s)
     Close a telnet session.

    void telnetd_prompt (struct telnetd_state *s, char *str)
     Print a prompt on a telnet connection.

    void telnetd_output (struct telnetd_state *s, char *str1, char *str2)
     Print out a string on a telnet connection.

    void telnetd_init (void)
     Initialize the telnet server.

    +
    Generated on Tue Oct 7 15:51:17 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00063.html b/doc/html/a00063.html new file mode 100644 index 0000000..3da5afc --- /dev/null +++ b/doc/html/a00063.html @@ -0,0 +1,70 @@ + + +uIP 0.9: telnetd.h File Reference + + + + +

    apps/telnetd/telnetd.h File Reference


    Detailed Description

    +Header file for the telnet server. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    + +

    +Include dependency graph for telnetd.h:

    Include dependency graph
    + + + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Data Structures

    struct  telnetd_state
     A telnet connection structure. More...


    Defines

    +#define TELNETD_LINELEN
     The maximum length of a telnet line.

    +#define TELNETD_NUMLINES
     The number of output lines being buffered for all telnet connections.


    Functions

    void telnetd_connected (struct telnetd_state *s)
     Callback function that is called when a telnet connection has been established.

    void telnetd_input (struct telnetd_state *s, char *cmd)
     Callback function that is called when a line of text has arrived on a telnet connection.

    void telnetd_close (struct telnetd_state *s)
     Close a telnet session.

    void telnetd_output (struct telnetd_state *s, char *s1, char *s2)
     Print out a string on a telnet connection.

    void telnetd_prompt (struct telnetd_state *s, char *str)
     Print a prompt on a telnet connection.

    void telnetd_init (void)
     Initialize the telnet server.

    +
    Generated on Tue Oct 7 15:51:21 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00064.html b/doc/html/a00064.html new file mode 100644 index 0000000..8a5acfd --- /dev/null +++ b/doc/html/a00064.html @@ -0,0 +1,60 @@ + + +uIP 0.9: webclient.c File Reference + + + + +

    apps/webclient/webclient.c File Reference


    Detailed Description

    +Implementation of the HTTP client. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    +#include "webclient.h"
    +#include "resolv.h"
    +#include <string.h>
    + +

    +Include dependency graph for webclient.c:

    Include dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    char * webclient_mimetype (void)
     Obtain the MIME type of the current HTTP data stream.

    char * webclient_filename (void)
     Obtain the filename of the current HTTP data stream.

    char * webclient_hostname (void)
     Obtain the hostname of the current HTTP data stream.

    unsigned short webclient_port (void)
     Obtain the port number of the current HTTP data stream.

    +void webclient_init (void)
     Initialize the webclient module.

    +void webclient_close (void)
     Close the currently open HTTP connection.

    unsigned char webclient_get (char *host, u16_t port, char *file)
     Open an HTTP connection to a web server and ask for a file using the GET method.

    +
    Generated on Tue Oct 7 15:51:24 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00065.html b/doc/html/a00065.html new file mode 100644 index 0000000..7a9e0fe --- /dev/null +++ b/doc/html/a00065.html @@ -0,0 +1,72 @@ + + +uIP 0.9: webclient.h File Reference + + + + +

    apps/webclient/webclient.h File Reference


    Detailed Description

    +Header file for the HTTP client. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "http-strings.h"
    +#include "http-user-agent-string.h"
    + +

    +Include dependency graph for webclient.h:

    Include dependency graph
    + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    void webclient_datahandler (char *data, u16_t len)
     Callback function that is called from the webclient code when HTTP data has been received.

    void webclient_connected (void)
     Callback function that is called from the webclient code when the HTTP connection has been connected to the web server.

    void webclient_timedout (void)
     Callback function that is called from the webclient code if the HTTP connection to the web server has timed out.

    void webclient_aborted (void)
     Callback function that is called from the webclient code if the HTTP connection to the web server has been aborted by the web server.

    void webclient_closed (void)
     Callback function that is called from the webclient code when the HTTP connection to the web server has been closed.

    +void webclient_init (void)
     Initialize the webclient module.

    unsigned char webclient_get (char *host, u16_t port, char *file)
     Open an HTTP connection to a web server and ask for a file using the GET method.

    +void webclient_close (void)
     Close the currently open HTTP connection.

    char * webclient_mimetype (void)
     Obtain the MIME type of the current HTTP data stream.

    char * webclient_filename (void)
     Obtain the filename of the current HTTP data stream.

    char * webclient_hostname (void)
     Obtain the hostname of the current HTTP data stream.

    unsigned short webclient_port (void)
     Obtain the port number of the current HTTP data stream.

    +
    Generated on Tue Oct 7 15:51:29 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00067.html b/doc/html/a00067.html new file mode 100644 index 0000000..984f8a1 --- /dev/null +++ b/doc/html/a00067.html @@ -0,0 +1,41 @@ + + +uIP 0.9: slipdev.c File Reference + + + + +

    uip/slipdev.c File Reference


    Detailed Description

    +SLIP protocol implementation. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    + +

    +Include dependency graph for slipdev.c:

    Include dependency graph
    + + + + + + + + + + + + + + + + + +

    Functions

    void slipdev_send (void)
     Send the packet in the uip_buf and uip_appdata buffers using the SLIP protocol.

    u16_t slipdev_poll (void)
     Poll the SLIP device for an available packet.

    void slipdev_init (void)
     Initialize the SLIP module.

    +
    Generated on Tue Oct 7 15:51:30 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00068.html b/doc/html/a00068.html new file mode 100644 index 0000000..0fb5a0d --- /dev/null +++ b/doc/html/a00068.html @@ -0,0 +1,47 @@ + + +uIP 0.9: slipdev.h File Reference + + + + +

    uip/slipdev.h File Reference


    Detailed Description

    +SLIP header file. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    + +

    +Include dependency graph for slipdev.h:

    Include dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    void slipdev_char_put (u8_t c)
     Put a character on the serial device.

    u8_t slipdev_char_poll (u8_t *c)
     Poll the serial device for a character.

    void slipdev_init (void)
     Initialize the SLIP module.

    void slipdev_send (void)
     Send the packet in the uip_buf and uip_appdata buffers using the SLIP protocol.

    u16_t slipdev_poll (void)
     Poll the SLIP device for an available packet.

    +
    Generated on Tue Oct 7 15:51:31 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00069.html b/doc/html/a00069.html new file mode 100644 index 0000000..ed3c40f --- /dev/null +++ b/doc/html/a00069.html @@ -0,0 +1,61 @@ + + +uIP 0.9: uip.c File Reference + + + + +

    uip/uip.c File Reference


    Detailed Description

    +The uIP TCP/IP stack code. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    +#include "uipopt.h"
    +#include "uip_arch.h"
    + +

    +Include dependency graph for uip.c:

    Include dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    void uip_init (void)
     uIP initialization function.

    uip_udp_connuip_udp_new (u16_t *ripaddr, u16_t rport)
     Set up a new UDP connection.

    void uip_unlisten (u16_t port)
     Stop listening to the specified port.

    void uip_listen (u16_t port)
     Start listening to the specified port.

    u16_t htons (u16_t val)
     Convert 16-bit quantity from host byte order to network byte order.


    Variables

    u8_t uip_buf [UIP_BUFSIZE+2]
     The uIP packet buffer.

    volatile u8_tuip_appdata
     Pointer to the application data in the packet buffer.

    +volatile u8_t uip_acc32 [4]
     4-byte array used for the 32-bit sequence number calculations.

    +
    Generated on Tue Oct 7 15:51:32 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00070.html b/doc/html/a00070.html new file mode 100644 index 0000000..6d71f1d --- /dev/null +++ b/doc/html/a00070.html @@ -0,0 +1,183 @@ + + +uIP 0.9: uip.h File Reference + + + + +

    uip/uip.h File Reference


    Detailed Description

    +Header file for the uIP TCP/IP stack. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    +The uIP TCP/IP stack header file contains definitions for a number of C macros that are used by uIP programs as well as internal uIP structures, TCP/IP header structures and function declarations. +

    +#include "uipopt.h"
    + +

    +Include dependency graph for uip.h:

    Include dependency graph
    + + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Data Structures

    struct  uip_conn
     Representation of a uIP TCP connection. More...

    struct  uip_stats
     The structure holding the TCP/IP statistics that are gathered if UIP_STATISTICS is set to 1. More...

    struct  uip_udp_conn
     Representation of a uIP UDP connection. More...


    Defines

    #define uip_sethostaddr(addr)
     Set the IP address of this host.

    #define uip_gethostaddr(addr)
     Get the IP address of this host.

    #define uip_input()
     Process an incoming packet.

    #define uip_periodic(conn)
     Periodic processing for a connection identified by its number.

    #define uip_periodic_conn(conn)
     Periodic processing for a connection identified by a pointer to its structure.

    #define uip_udp_periodic(conn)
     Periodic processing for a UDP connection identified by its number.

    #define uip_udp_periodic_conn(conn)
     Periodic processing for a UDP connection identified by a pointer to its structure.

    #define uip_send(data, len)
     Send data on the current connection.

    #define uip_datalen()
     The length of any incoming data that is currently avaliable (if avaliable) in the uip_appdata buffer.

    #define uip_urgdatalen()
     The length of any out-of-band data (urgent data) that has arrived on the connection.

    #define uip_close()
     Close the current connection.

    #define uip_abort()
     Abort the current connection.

    #define uip_stop()
     Tell the sending host to stop sending data.

    +#define uip_stopped(conn)
     Find out if the current connection has been previously stopped with uip_stop().

    #define uip_restart()
     Restart the current connection, if is has previously been stopped with uip_stop().

    #define uip_newdata()
     Is new incoming data available?

    #define uip_acked()
     Has previously sent data been acknowledged?

    #define uip_connected()
     Has the connection just been connected?

    #define uip_closed()
     Has the connection been closed by the other end?

    #define uip_aborted()
     Has the connection been aborted by the other end?

    #define uip_timedout()
     Has the connection timed out?

    #define uip_rexmit()
     Do we need to retransmit previously data?

    #define uip_poll()
     Is the connection being polled by uIP?

    +#define uip_initialmss()
     Get the initial maxium segment size (MSS) of the current connection.

    #define uip_mss()
     Get the current maxium segment size that can be sent on the current connection.

    #define uip_udp_remove(conn)
     Removed a UDP connection.

    #define uip_udp_send(len)
     Send a UDP datagram of length len on the current connection.

    #define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
     Pack an IP address into a 4-byte array which is used by uIP to represent IP addresses.

    #define HTONS(n)
     Convert 16-bit quantity from host byte order to network byte order.


    Functions

    void uip_init (void)
     uIP initialization function.

    void uip_listen (u16_t port)
     Start listening to the specified port.

    void uip_unlisten (u16_t port)
     Stop listening to the specified port.

    uip_connuip_connect (u16_t *ripaddr, u16_t port)
     Connect to a remote host using TCP.

    uip_udp_connuip_udp_new (u16_t *ripaddr, u16_t rport)
     Set up a new UDP connection.

    u16_t htons (u16_t val)
     Convert 16-bit quantity from host byte order to network byte order.


    Variables

    u8_t uip_buf [UIP_BUFSIZE+2]
     The uIP packet buffer.

    volatile u8_tuip_appdata
     Pointer to the application data in the packet buffer.

    +volatile u8_t uip_acc32 [4]
     4-byte array used for the 32-bit sequence number calculations.

    uip_stats uip_stat
     The uIP TCP/IP statistics.

    +
    Generated on Tue Oct 7 15:51:34 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00071.html b/doc/html/a00071.html new file mode 100644 index 0000000..f2348e6 --- /dev/null +++ b/doc/html/a00071.html @@ -0,0 +1,50 @@ + + +uIP 0.9: uip_arch.h File Reference + + + + +

    uip/uip_arch.h File Reference


    Detailed Description

    +Declarations of architecture specific functions. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    + +

    +Include dependency graph for uip_arch.h:

    Include dependency graph
    + + + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + +

    Functions

    void uip_add32 (u8_t *op32, u16_t op16)
     Carry out a 32-bit addition.

    u16_t uip_chksum (u16_t *buf, u16_t len)
     Calculate the Internet checksum over a buffer.

    u16_t uip_ipchksum (void)
     Calculate the IP header checksum of the packet header in uip_buf.

    u16_t uip_tcpchksum (void)
     Calculate the TCP checksum of the packet in uip_buf and uip_appdata.

    +
    Generated on Tue Oct 7 15:51:36 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00072.html b/doc/html/a00072.html new file mode 100644 index 0000000..01fc222 --- /dev/null +++ b/doc/html/a00072.html @@ -0,0 +1,50 @@ + + +uIP 0.9: uip_arp.c File Reference + + + + +

    uip/uip_arp.c File Reference


    Detailed Description

    +Implementation of the ARP Address Resolution Protocol. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip_arp.h"
    +#include <string.h>
    + +

    +Include dependency graph for uip_arp.c:

    Include dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + +

    Functions

    +void uip_arp_init (void)
     Initialize the ARP module.

    void uip_arp_timer (void)
     Periodic ARP processing function.

    void uip_arp_ipin (void)
     ARP processing for incoming IP packets.

    void uip_arp_arpin (void)
     ARP processing for incoming ARP packets.

    void uip_arp_out (void)
     Prepend Ethernet header to an outbound IP packet and see if we need to send out an ARP request.

    +
    Generated on Tue Oct 7 15:51:37 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00073.html b/doc/html/a00073.html new file mode 100644 index 0000000..483b616 --- /dev/null +++ b/doc/html/a00073.html @@ -0,0 +1,77 @@ + + +uIP 0.9: uip_arp.h File Reference + + + + +

    uip/uip_arp.h File Reference


    Detailed Description

    +Macros and definitions for the ARP module. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    + +

    +#include "uip.h"
    + +

    +Include dependency graph for uip_arp.h:

    Include dependency graph
    + + + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Data Structures

    struct  uip_eth_addr
     Representation of a 48-bit Ethernet address. More...

    struct  uip_eth_hdr
     The Ethernet header. More...


    Defines

    #define uip_setdraddr(addr)
     Set the default router's IP address.

    #define uip_setnetmask(addr)
     Set the netmask.

    #define uip_getdraddr(addr)
     Get the default router's IP address.

    #define uip_getnetmask(addr)
     Get the netmask.

    #define uip_setethaddr(eaddr)
     Specifiy the Ethernet MAC address.


    Functions

    +void uip_arp_init (void)
     Initialize the ARP module.

    void uip_arp_ipin (void)
     ARP processing for incoming IP packets.

    void uip_arp_arpin (void)
     ARP processing for incoming ARP packets.

    void uip_arp_out (void)
     Prepend Ethernet header to an outbound IP packet and see if we need to send out an ARP request.

    void uip_arp_timer (void)
     Periodic ARP processing function.

    +
    Generated on Tue Oct 7 15:51:39 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00074.html b/doc/html/a00074.html new file mode 100644 index 0000000..1cb69e1 --- /dev/null +++ b/doc/html/a00074.html @@ -0,0 +1,209 @@ + + +uIP 0.9: uipopt.h File Reference + + + + +

    unix/uipopt.h File Reference


    Detailed Description

    +Configuration options for uIP. +

    +

    Author:
    Adam Dunkels <adam@dunkels.com>
    +This file is used for tweaking various configuration options for uIP. You should make a copy of this file into one of your project's directories instead of editing this example "uipopt.h" file that comes with the uIP distribution. +

    +#include "httpd.h"
    + +

    +Include dependency graph for uipopt.h:

    Include dependency graph
    + + + + +

    +This graph shows which files directly or indirectly include this file:

    Included by dependency graph
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    #define UIP_FIXEDADDR
     Determines if uIP should use a fixed IP address or not.

    #define UIP_PINGADDRCONF
     Ping IP address asignment.

    +#define UIP_IPADDR0
     The first octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_IPADDR1
     The second octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_IPADDR2
     The third octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_IPADDR3
     The fourth octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK0
     The first octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK1
     The second octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK2
     The third octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK3
     The fourth octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR0
     The first octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR1
     The second octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR2
     The third octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR3
     The fourth octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    #define UIP_FIXEDETHADDR
     Specifies if the uIP ARP module should be compiled with a fixed Ethernet MAC address or not.

    +#define UIP_ETHADDR0
     The first octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR1
     The second octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR2
     The third octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR3
     The fourth octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR4
     The fifth octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR5
     The sixth octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    #define UIP_TTL   255
     The IP TTL (time to live) of IP packets sent by uIP.

    #define UIP_REASSEMBLY
     Turn on support for IP packet reassembly.

    +#define UIP_REASS_MAXAGE   40
     The maximum time an IP fragment should wait in the reassembly buffer before it is dropped.

    +#define UIP_UDP
     Toggles wether UDP support should be compiled in or not.

    #define UIP_UDP_CHECKSUMS
     Toggles if UDP checksums should be used or not.

    +#define UIP_UDP_CONNS
     The maximum amount of concurrent UDP connections.

    +#define UIP_UDP_APPCALL
     The name of the function that should be called when UDP datagrams arrive.

    #define UIP_ACTIVE_OPEN
     Determines if support for opening connections from uIP should be compiled in.

    #define UIP_CONNS
     The maximum number of simultaneously open TCP connections.

    #define UIP_LISTENPORTS
     The maximum number of simultaneously listening TCP ports.

    #define UIP_RECEIVE_WINDOW
     The size of the advertised receiver's window.

    #define UIP_URGDATA
     Determines if support for TCP urgent data notification should be compiled in.

    #define UIP_RTO   3
     The initial retransmission timeout counted in timer pulses.

    #define UIP_MAXRTX   8
     The maximum number of times a segment should be retransmitted before the connection should be aborted.

    #define UIP_MAXSYNRTX   3
     The maximum number of times a SYN segment should be retransmitted before a connection request should be deemed to have been unsuccessful.

    #define UIP_TCP_MSS   (UIP_BUFSIZE - UIP_LLH_LEN - 40)
     The TCP maximum segment size.

    #define UIP_TIME_WAIT_TIMEOUT   120
     How long a connection should stay in the TIME_WAIT state.

    #define UIP_ARPTAB_SIZE
     The size of the ARP table.

    #define UIP_ARP_MAXAGE   120
     The maxium age of ARP table entries measured in 10ths of seconds.

    #define UIP_BUFSIZE
     The size of the uIP packet buffer.

    #define UIP_STATISTICS
     Determines if statistics support should be compiled in.

    #define UIP_LOGGING
     Determines if logging of certain events should be compiled in.

    #define UIP_LLH_LEN
     The link level header length.

    #define BYTE_ORDER
     The byte order of the CPU architecture on which uIP is to be run.


    Typedefs

    typedef unsigned char u8_t
     The 8-bit unsigned data type.

    typedef unsigned short u16_t
     The 16-bit unsigned data type.

    typedef unsigned short uip_stats_t
     The statistics data type.


    Functions

    void uip_log (char *msg)
     Print out a uIP log message.

    +
    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00075.html b/doc/html/a00075.html new file mode 100644 index 0000000..3cc54a6 --- /dev/null +++ b/doc/html/a00075.html @@ -0,0 +1,358 @@ + + +uIP 0.9: The uIP TCP/IP stack + + + + +

    The uIP TCP/IP stack

    +

    + + + + + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Files

    file  uip.c
     The uIP TCP/IP stack code.

    file  uip.h
     Header file for the uIP TCP/IP stack.


    Modules

    uIP configuration functions
    uIP initialization functions
    uIP device driver functions
    uIP application functions
    uIP conversion functions
    uIP Address Resolution Protocol
    Serial Line IP (SLIP) protocol
    uIP hostname resolver functions
    Architecture specific uIP functions

    Data Structures

    struct  uip_conn
     Representation of a uIP TCP connection. More...

    struct  uip_stats
     The structure holding the TCP/IP statistics that are gathered if UIP_STATISTICS is set to 1. More...

    struct  uip_udp_conn
     Representation of a uIP UDP connection. More...


    Functions

    void uip_init (void)
     uIP initialization function.

    uip_udp_connuip_udp_new (u16_t *ripaddr, u16_t rport)
     Set up a new UDP connection.

    void uip_unlisten (u16_t port)
     Stop listening to the specified port.

    void uip_listen (u16_t port)
     Start listening to the specified port.

    u16_t htons (u16_t val)
     Convert 16-bit quantity from host byte order to network byte order.


    Variables

    volatile u8_tuip_appdata
     Pointer to the application data in the packet buffer.

    uip_stats uip_stat
     The uIP TCP/IP statistics.

    u8_t uip_buf [UIP_BUFSIZE+2]
     The uIP packet buffer.

    +volatile u8_t uip_acc32 [4]
     4-byte array used for the 32-bit sequence number calculations.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    u16_t htons u16_t  val  ) 
    +
    + + + + + +
    +   + + +

    +Convert 16-bit quantity from host byte order to network byte order. +

    +This function is primarily used for converting variables from host byte order to network byte order. For converting constants to network byte order, use the HTONS() macro instead.

    +

    + + + + +
    + + + + + + + + + + +
    void uip_init void   ) 
    +
    + + + + + +
    +   + + +

    +uIP initialization function. +

    +This function should be called at boot up to initilize the uIP TCP/IP stack.

    +

    + + + + +
    + + + + + + + + + + +
    void uip_listen u16_t  port  ) 
    +
    + + + + + +
    +   + + +

    +Start listening to the specified port. +

    +

    Note:
    Since this function expects the port number in network byte order, a conversion using HTONS() or htons() is necessary.
    +
     uip_listen(HTONS(80)); 
    +

    +

    Parameters:
    + + +
    port A 16-bit port number in network byte order.
    +
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    struct uip_udp_conn* uip_udp_new u16_t ripaddr,
    u16_t  rport
    +
    + + + + + +
    +   + + +

    +Set up a new UDP connection. +

    +

    Parameters:
    + + + +
    ripaddr A pointer to a 4-byte structure representing the IP address of the remote host.
    rport The remote port number in network byte order.
    +
    +
    Returns:
    The uip_udp_conn structure for the new connection or NULL if no connection could be allocated.
    +
    +

    + + + + +
    + + + + + + + + + + +
    void uip_unlisten u16_t  port  ) 
    +
    + + + + + +
    +   + + +

    +Stop listening to the specified port. +

    +

    Note:
    Since this function expects the port number in network byte order, a conversion using HTONS() or htons() is necessary.
    +

    +

    Parameters:
    + + +
    port A 16-bit port number in network byte order.
    +
    +
    +


    Variable Documentation

    +

    + + + + +
    + + +
    volatile u8_t* uip_appdata +
    +
    + + + + + +
    +   + + +

    +Pointer to the application data in the packet buffer. +

    +This pointer points to the application data when the application is called. If the application wishes to send data, the application may use this space to write the data into before calling uip_send().

    +

    + + + + +
    + + +
    u8_t uip_buf[UIP_BUFSIZE+2] +
    +
    + + + + + +
    +   + + +

    +The uIP packet buffer. +

    +The uip_buf array is used to hold incoming and outgoing packets. The device driver should place incoming data into this buffer. When sending data, the device driver should read the link level headers and the TCP/IP headers from this buffer. The size of the link level headers is configured by the UIP_LLH_LEN define.

    +

    Note:
    The application data need not be placed in this buffer, so the device driver must read it from the place pointed to by the uip_appdata pointer as illustrated by the following example:
     void
    + devicedriver_send(void)
    + {
    +    hwsend(&uip_buf[0], UIP_LLH_LEN);
    +    hwsend(&uip_buf[UIP_LLH_LEN], 40);
    +    hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN);
    + }
    +
    +
    +

    + + + + +
    + + +
    struct uip_stats uip_stat +
    +
    + + + + + +
    +   + + +

    +The uIP TCP/IP statistics. +

    +This is the variable in which the uIP TCP/IP statistics are gathered.

    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00076.html b/doc/html/a00076.html new file mode 100644 index 0000000..5bfedb8 --- /dev/null +++ b/doc/html/a00076.html @@ -0,0 +1,269 @@ + + +uIP 0.9: Example applications + + + + +

    Example applications


    Detailed Description

    +The uIP distribution contains a number of example applications that can be either used directory or studied when learning to develop applications for uIP. +

    + + + + + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + +

    Files

    file  memb.c
     Memory block allocation routines.

    file  memb.h
     Memory block allocation routines.


    Modules

    Web client
    SMTP E-mail sender
    Telnet server
    Web server

    Defines

    #define MEMB(name, size, num)
     Declare a memory block.


    Functions

    void memb_init (struct memb_blocks *m)
     Initialize a memory block that was declared with MEMB().

    char * memb_alloc (struct memb_blocks *m)
     Allocate a memory block from a block of memory declared with MEMB().

    char memb_ref (struct memb_blocks *m, char *ptr)
     Increase the reference count for a memory chunk.

    char memb_free (struct memb_blocks *m, char *ptr)
     Deallocate a memory block from a memory block previously declared with MEMB().

    +


    Define Documentation

    +

    + + + + +
    + + + + + + + + + + + + + +
    #define MEMBname,
    size,
    num   )  +
    +
    + + + + + +
    +   + + +

    +Value:

    static char memb_mem[(size + 1) * num]; \
    +        static struct memb_blocks name = {size, num, memb_mem}
    +
    Declare a memory block. +

    +

    Parameters:
    + + + + +
    name The name of the memory block (later used with memb_init(), memb_alloc() and memb_free()).
    size The size of each memory chunk, in bytes.
    num The total number of memory chunks in the block.
    +
    +
    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    char* memb_alloc struct memb_blocks *  m  ) 
    +
    + + + + + +
    +   + + +

    +Allocate a memory block from a block of memory declared with MEMB(). +

    +

    Parameters:
    + + +
    m A memory block previosly declared with MEMB().
    +
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    char memb_free struct memb_blocks *  m,
    char *  ptr
    +
    + + + + + +
    +   + + +

    +Deallocate a memory block from a memory block previously declared with MEMB(). +

    +

    Parameters:
    + + + +
    m m A memory block previosly declared with MEMB().
    ptr A pointer to the memory block that is to be deallocated.
    +
    +
    Returns:
    The new reference count for the memory block (should be 0 if successfully deallocated) or -1 if the pointer "ptr" did not point to a legal memory block.
    +
    +

    + + + + +
    + + + + + + + + + + +
    void memb_init struct memb_blocks *  m  ) 
    +
    + + + + + +
    +   + + +

    +Initialize a memory block that was declared with MEMB(). +

    +

    Parameters:
    + + +
    m A memory block previosly declared with MEMB().
    +
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    char memb_ref struct memb_blocks *  m,
    char *  ptr
    +
    + + + + + +
    +   + + +

    +Increase the reference count for a memory chunk. +

    +

    Note:
    No sanity checks are currently made.
    +
    Parameters:
    + + + +
    m m A memory block previosly declared with MEMB().
    ptr A pointer to the memory chunk for which the reference count should be increased.
    +
    +
    Returns:
    The new reference count.
    +
    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00077.html b/doc/html/a00077.html new file mode 100644 index 0000000..6ad8ec3 --- /dev/null +++ b/doc/html/a00077.html @@ -0,0 +1,287 @@ + + +uIP 0.9: uIP configuration functions + + + + +

    uIP configuration functions
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +The uIP configuration functions are used for setting run-time parameters in uIP such as IP addresses. +

    + + + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    #define uip_sethostaddr(addr)
     Set the IP address of this host.

    #define uip_gethostaddr(addr)
     Get the IP address of this host.

    #define uip_setdraddr(addr)
     Set the default router's IP address.

    #define uip_setnetmask(addr)
     Set the netmask.

    #define uip_getdraddr(addr)
     Get the default router's IP address.

    #define uip_getnetmask(addr)
     Get the netmask.

    #define uip_setethaddr(eaddr)
     Specifiy the Ethernet MAC address.

    +


    Define Documentation

    +

    + + + + +
    + + + + + + + +
    #define uip_getdraddraddr   )  +
    +
    + + + + + +
    +   + + +

    +Get the default router's IP address. +

    +

    Parameters:
    + + +
    addr A pointer to a 4-byte array that will be filled in with the IP address of the default router.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_gethostaddraddr   )  +
    +
    + + + + + +
    +   + + +

    +Get the IP address of this host. +

    +The IP address is represented as a 4-byte array where the first octet of the IP address is put in the first member of the 4-byte array.

    +

    Parameters:
    + + +
    addr A pointer to a 4-byte array that will be filled in with the currently configured IP address.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_getnetmaskaddr   )  +
    +
    + + + + + +
    +   + + +

    +Get the netmask. +

    +

    Parameters:
    + + +
    addr A pointer to a 4-byte array that will be filled in with the value of the netmask.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_setdraddraddr   )  +
    +
    + + + + + +
    +   + + +

    +Set the default router's IP address. +

    +

    Parameters:
    + + +
    addr A pointer to a 4-byte array containing the IP address of the default router.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_setethaddreaddr   )  +
    +
    + + + + + +
    +   + + +

    +Specifiy the Ethernet MAC address. +

    +The ARP code needs to know the MAC address of the Ethernet card in order to be able to respond to ARP queries and to generate working Ethernet headers.

    +

    Note:
    This macro only specifies the Ethernet MAC address to the ARP code. It cannot be used to change the MAC address of the Ethernet card.
    +
    Parameters:
    + + +
    eaddr A pointer to a struct uip_eth_addr containing the Ethernet MAC address of the Ethernet card.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_sethostaddraddr   )  +
    +
    + + + + + +
    +   + + +

    +Set the IP address of this host. +

    +The IP address is represented as a 4-byte array where the first octet of the IP address is put in the first member of the 4-byte array.

    +

    Parameters:
    + + +
    addr A pointer to a 4-byte representation of the IP address.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_setnetmaskaddr   )  +
    +
    + + + + + +
    +   + + +

    +Set the netmask. +

    +

    Parameters:
    + + +
    addr A pointer to a 4-byte array containing the IP address of the netmask.
    +
    +
    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00078.html b/doc/html/a00078.html new file mode 100644 index 0000000..92b7416 --- /dev/null +++ b/doc/html/a00078.html @@ -0,0 +1,58 @@ + + +uIP 0.9: uIP initialization functions + + + + +

    uIP initialization functions
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +The uIP initialization functions are used for booting uIP. +

    + + + + + + +

    Functions

    void uip_init (void)
     uIP initialization function.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    void uip_init void   ) 
    +
    + + + + + +
    +   + + +

    +uIP initialization function. +

    +This function should be called at boot up to initilize the uIP TCP/IP stack.

    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00079.html b/doc/html/a00079.html new file mode 100644 index 0000000..7324265 --- /dev/null +++ b/doc/html/a00079.html @@ -0,0 +1,303 @@ + + +uIP 0.9: uIP device driver functions + + + + +

    uIP device driver functions
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +These functions are used by a network device driver for interacting with uIP. +

    + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    #define uip_input()
     Process an incoming packet.

    #define uip_periodic(conn)
     Periodic processing for a connection identified by its number.

    #define uip_periodic_conn(conn)
     Periodic processing for a connection identified by a pointer to its structure.

    #define uip_udp_periodic(conn)
     Periodic processing for a UDP connection identified by its number.

    #define uip_udp_periodic_conn(conn)
     Periodic processing for a UDP connection identified by a pointer to its structure.


    Variables

    u8_t uip_buf [UIP_BUFSIZE+2]
     The uIP packet buffer.

    +


    Define Documentation

    +

    + + + + +
    + + + + +  + + +
    #define uip_input  )  +
    +
    + + + + + +
    +   + + +

    +Process an incoming packet. +

    +This function should be called when the device driver has received a packet from the network. The packet from the device driver must be present in the uip_buf buffer, and the length of the packet should be placed in the uip_len variable.

    +When the function returns, there may be an outbound packet placed in the uip_buf packet buffer. If so, the uip_len variable is set to the length of the packet. If no packet is to be sent out, the uip_len variable is set to 0.

    +The usual way of calling the function is presented by the source code below.

      uip_len = devicedriver_poll();
    +  if(uip_len > 0) {
    +    uip_input();
    +    if(uip_len > 0) {
    +      devicedriver_send();
    +    }
    +  }
    +

    +

    Note:
    If you are writing a uIP device driver that needs ARP (Address Resolution Protocol), e.g., when running uIP over Ethernet, you will need to call the uIP ARP code before calling this function:
      #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
    +  uip_len = ethernet_devicedrver_poll();
    +  if(uip_len > 0) {
    +    if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
    +      uip_arp_ipin();
    +      uip_input();
    +      if(uip_len > 0) {
    +        uip_arp_out();
    +        ethernet_devicedriver_send();
    +      }
    +    } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
    +      uip_arp_arpin();
    +      if(uip_len > 0) {
    +        ethernet_devicedriver_send();
    +      }
    +    }
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_periodicconn   )  +
    +
    + + + + + +
    +   + + +

    +Periodic processing for a connection identified by its number. +

    +This function does the necessary periodic processing (timers, polling) for a uIP TCP conneciton, and should be called when the periodic uIP timer goes off. It should be called for every connection, regardless of whether they are open of closed.

    +When the function returns, it may have an outbound packet waiting for service in the uIP packet buffer, and if so the uip_len variable is set to a value larger than zero. The device driver should be called to send out the packet.

    +The ususal way of calling the function is through a for() loop like this:

      for(i = 0; i < UIP_CONNS; ++i) {
    +    uip_periodic(i);
    +    if(uip_len > 0) {
    +      devicedriver_send();
    +    }
    +  }
    +

    +

    Note:
    If you are writing a uIP device driver that needs ARP (Address Resolution Protocol), e.g., when running uIP over Ethernet, you will need to call the uip_arp_out() function before calling the device driver:
      for(i = 0; i < UIP_CONNS; ++i) {
    +    uip_periodic(i);
    +    if(uip_len > 0) {
    +      uip_arp_out();
    +      ethernet_devicedriver_send();
    +    }
    +  }
    +
    +
    Parameters:
    + + +
    conn The number of the connection which is to be periodically polled.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_periodic_connconn   )  +
    +
    + + + + + +
    +   + + +

    +Periodic processing for a connection identified by a pointer to its structure. +

    +Same as uip_periodic() but takes a pointer to the actual uip_conn struct instead of an integer as its argument. This function can be used to force periodic processing of a specific connection.

    +

    Parameters:
    + + +
    conn A pointer to the uip_conn struct for the connection to be processed.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_udp_periodicconn   )  +
    +
    + + + + + +
    +   + + +

    +Periodic processing for a UDP connection identified by its number. +

    +This function is essentially the same as uip_prerioic(), but for UDP connections. It is called in a similar fashion as the uip_periodic() function:

      for(i = 0; i < UIP_UDP_CONNS; i++) {
    +    uip_udp_periodic(i);
    +    if(uip_len > 0) {
    +      devicedriver_send();
    +    }
    +  }   
    +

    +

    Note:
    As for the uip_periodic() function, special care has to be taken when using uIP together with ARP and Ethernet:
      for(i = 0; i < UIP_UDP_CONNS; i++) {
    +    uip_udp_periodic(i);
    +    if(uip_len > 0) {
    +      uip_arp_out();
    +      ethernet_devicedriver_send();
    +    }
    +  }   
    +
    +
    Parameters:
    + + +
    conn The number of the UDP connection to be processed.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_udp_periodic_connconn   )  +
    +
    + + + + + +
    +   + + +

    +Periodic processing for a UDP connection identified by a pointer to its structure. +

    +Same as uip_udp_periodic() but takes a pointer to the actual uip_conn struct instead of an integer as its argument. This function can be used to force periodic processing of a specific connection.

    +

    Parameters:
    + + +
    conn A pointer to the uip_udp_conn struct for the connection to be processed.
    +
    +
    +


    Variable Documentation

    +

    + + + + +
    + + +
    u8_t uip_buf[UIP_BUFSIZE+2] +
    +
    + + + + + +
    +   + + +

    +The uIP packet buffer. +

    +The uip_buf array is used to hold incoming and outgoing packets. The device driver should place incoming data into this buffer. When sending data, the device driver should read the link level headers and the TCP/IP headers from this buffer. The size of the link level headers is configured by the UIP_LLH_LEN define.

    +

    Note:
    The application data need not be placed in this buffer, so the device driver must read it from the place pointed to by the uip_appdata pointer as illustrated by the following example:
     void
    + devicedriver_send(void)
    + {
    +    hwsend(&uip_buf[0], UIP_LLH_LEN);
    +    hwsend(&uip_buf[UIP_LLH_LEN], 40);
    +    hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN);
    + }
    +
    +
    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00080.html b/doc/html/a00080.html new file mode 100644 index 0000000..b450f87 --- /dev/null +++ b/doc/html/a00080.html @@ -0,0 +1,827 @@ + + +uIP 0.9: uIP application functions + + + + +

    uIP application functions
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +Functions used by an application running of top of uIP. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    #define uip_send(data, len)
     Send data on the current connection.

    #define uip_datalen()
     The length of any incoming data that is currently avaliable (if avaliable) in the uip_appdata buffer.

    #define uip_urgdatalen()
     The length of any out-of-band data (urgent data) that has arrived on the connection.

    #define uip_close()
     Close the current connection.

    #define uip_abort()
     Abort the current connection.

    #define uip_stop()
     Tell the sending host to stop sending data.

    +#define uip_stopped(conn)
     Find out if the current connection has been previously stopped with uip_stop().

    #define uip_restart()
     Restart the current connection, if is has previously been stopped with uip_stop().

    #define uip_newdata()
     Is new incoming data available?

    #define uip_acked()
     Has previously sent data been acknowledged?

    #define uip_connected()
     Has the connection just been connected?

    #define uip_closed()
     Has the connection been closed by the other end?

    #define uip_aborted()
     Has the connection been aborted by the other end?

    #define uip_timedout()
     Has the connection timed out?

    #define uip_rexmit()
     Do we need to retransmit previously data?

    #define uip_poll()
     Is the connection being polled by uIP?

    +#define uip_initialmss()
     Get the initial maxium segment size (MSS) of the current connection.

    #define uip_mss()
     Get the current maxium segment size that can be sent on the current connection.

    #define uip_udp_remove(conn)
     Removed a UDP connection.

    #define uip_udp_send(len)
     Send a UDP datagram of length len on the current connection.


    Functions

    void uip_listen (u16_t port)
     Start listening to the specified port.

    void uip_unlisten (u16_t port)
     Stop listening to the specified port.

    uip_connuip_connect (u16_t *ripaddr, u16_t port)
     Connect to a remote host using TCP.

    uip_udp_connuip_udp_new (u16_t *ripaddr, u16_t rport)
     Set up a new UDP connection.

    +


    Define Documentation

    +

    + + + + +
    + + + + +  + + +
    #define uip_abort  )  +
    +
    + + + + + +
    +   + + +

    +Abort the current connection. +

    +This function will abort (reset) the current connection, and is usually used when an error has occured that prevents using the uip_close() function.

    +

    + + + + +
    + + + + +  + + +
    #define uip_aborted  )  +
    +
    + + + + + +
    +   + + +

    +Has the connection been aborted by the other end? +

    +Non-zero if the current connection has been aborted (reset) by the remote host.

    +

    + + + + +
    + + + + +  + + +
    #define uip_acked  )  +
    +
    + + + + + +
    +   + + +

    +Has previously sent data been acknowledged? +

    +Will reduce to non-zero if the previously sent data has been acknowledged by the remote host. This means that the application can send new data.

    +

    + + + + +
    + + + + +  + + +
    #define uip_close  )  +
    +
    + + + + + +
    +   + + +

    +Close the current connection. +

    +This function will close the current connection in a nice way.

    +

    + + + + +
    + + + + +  + + +
    #define uip_closed  )  +
    +
    + + + + + +
    +   + + +

    +Has the connection been closed by the other end? +

    +Is non-zero if the connection has been closed by the remote host. The application may then do the necessary clean-ups.

    +

    + + + + +
    + + + + +  + + +
    #define uip_connected  )  +
    +
    + + + + + +
    +   + + +

    +Has the connection just been connected? +

    +Reduces to non-zero if the current connection has been connected to a remote host. This will happen both if the connection has been actively opened (with uip_connect()) or passively opened (with uip_listen()).

    +

    + + + + +
    + + + + +  + + +
    #define uip_datalen  )  +
    +
    + + + + + +
    +   + + +

    +The length of any incoming data that is currently avaliable (if avaliable) in the uip_appdata buffer. +

    +The test function uip_data() must first be used to check if there is any data available at all.

    +

    + + + + +
    + + + + +  + + +
    #define uip_mss  )  +
    +
    + + + + + +
    +   + + +

    +Get the current maxium segment size that can be sent on the current connection. +

    +The current maxiumum segment size that can be sent on the connection is computed from the receiver's window and the MSS of the connection (which also is available by calling uip_initialmss()).

    +

    + + + + +
    + + + + +  + + +
    #define uip_newdata  )  +
    +
    + + + + + +
    +   + + +

    +Is new incoming data available? +

    +Will reduce to non-zero if there is new data for the application present at the uip_appdata pointer. The size of the data is avaliable through the uip_len variable.

    +

    + + + + +
    + + + + +  + + +
    #define uip_poll  )  +
    +
    + + + + + +
    +   + + +

    +Is the connection being polled by uIP? +

    +Is non-zero if the reason the application is invoked is that the current connection has been idle for a while and should be polled.

    +The polling event can be used for sending data without having to wait for the remote host to send data.

    +

    + + + + +
    + + + + +  + + +
    #define uip_restart  )  +
    +
    + + + + + +
    +   + + +

    +Restart the current connection, if is has previously been stopped with uip_stop(). +

    +This function will open the receiver's window again so that we start receiving data for the current connection.

    +

    + + + + +
    + + + + +  + + +
    #define uip_rexmit  )  +
    +
    + + + + + +
    +   + + +

    +Do we need to retransmit previously data? +

    +Reduces to non-zero if the previously sent data has been lost in the network, and the application should retransmit it. The application should send the exact same data as it did the last time, using the uip_send() function.

    +

    + + + + +
    + + + + + + + + + + +
    #define uip_senddata,
    len   )  +
    +
    + + + + + +
    +   + + +

    +Send data on the current connection. +

    +This function is used to send out a single segment of TCP data. Only applications that have been invoked by uIP for event processing can send data.

    +The amount of data that actually is sent out after a call to this funcion is determined by the maximum amount of data TCP allows. uIP will automatically crop the data so that only the appropriate amount of data is sent. The function uip_mss() can be used to query uIP for the amount of data that actually will be sent.

    +

    Note:
    This function does not guarantee that the sent data will arrive at the destination. If the data is lost in the network, the application will be invoked with the uip_rexmit() event being set. The application will then have to resend the data using this function.
    +
    Parameters:
    + + + +
    data A pointer to the data which is to be sent.
    len The maximum amount of data bytes to be sent.
    +
    +
    +

    + + + + +
    + + + + +  + + +
    #define uip_stop  )  +
    +
    + + + + + +
    +   + + +

    +Tell the sending host to stop sending data. +

    +This function will close our receiver's window so that we stop receiving data for the current connection.

    +

    + + + + +
    + + + + +  + + +
    #define uip_timedout  )  +
    +
    + + + + + +
    +   + + +

    +Has the connection timed out? +

    +Non-zero if the current connection has been aborted due to too many retransmissions.

    +

    + + + + +
    + + + + + + + +
    #define uip_udp_removeconn   )  +
    +
    + + + + + +
    +   + + +

    +Removed a UDP connection. +

    +

    Parameters:
    + + +
    conn A pointer to the uip_udp_conn structure for the connection.
    +
    +
    +

    + + + + +
    + + + + + + + +
    #define uip_udp_sendlen   )  +
    +
    + + + + + +
    +   + + +

    +Send a UDP datagram of length len on the current connection. +

    +This function can only be called in response to a UDP event (poll or newdata). The data must be present in the uip_buf buffer, at the place pointed to by the uip_appdata pointer.

    +

    Parameters:
    + + +
    len The length of the data in the uip_buf buffer.
    +
    +
    +

    + + + + +
    + + + + +  + + +
    #define uip_urgdatalen  )  +
    +
    + + + + + +
    +   + + +

    +The length of any out-of-band data (urgent data) that has arrived on the connection. +

    +

    Note:
    The configuration parameter UIP_URGDATA must be set for this function to be enabled.
    +
    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    struct uip_conn* uip_connect u16_t ripaddr,
    u16_t  port
    +
    + + + + + +
    +   + + +

    +Connect to a remote host using TCP. +

    +This function is used to start a new connection to the specified port on the specied host. It allocates a new connection identifier, sets the connection to the SYN_SENT state and sets the retransmission timer to 0. This will cause a TCP SYN segment to be sent out the next time this connection is periodically processed, which usually is done within 0.5 seconds after the call to uip_connect().

    +

    Note:
    This function is avaliable only if support for active open has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h.

    +Since this function requires the port number to be in network byte order, a convertion using HTONS() or htons() is necessary.

    +
     u16_t ipaddr[2];
    +
    + uip_ipaddr(ipaddr, 192,168,1,2);
    + uip_connect(ipaddr, HTONS(80)); 
    +

    +

    Parameters:
    + + + +
    ripaddr A pointer to a 4-byte array representing the IP address of the remote hot.
    port A 16-bit port number in network byte order.
    +
    +
    Returns:
    A pointer to the uIP connection identifier for the new connection, or NULL if no connection could be allocated.
    +
    +

    + + + + +
    + + + + + + + + + + +
    void uip_listen u16_t  port  ) 
    +
    + + + + + +
    +   + + +

    +Start listening to the specified port. +

    +

    Note:
    Since this function expects the port number in network byte order, a conversion using HTONS() or htons() is necessary.
    +
     uip_listen(HTONS(80)); 
    +

    +

    Parameters:
    + + +
    port A 16-bit port number in network byte order.
    +
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    struct uip_udp_conn* uip_udp_new u16_t ripaddr,
    u16_t  rport
    +
    + + + + + +
    +   + + +

    +Set up a new UDP connection. +

    +

    Parameters:
    + + + +
    ripaddr A pointer to a 4-byte structure representing the IP address of the remote host.
    rport The remote port number in network byte order.
    +
    +
    Returns:
    The uip_udp_conn structure for the new connection or NULL if no connection could be allocated.
    +
    +

    + + + + +
    + + + + + + + + + + +
    void uip_unlisten u16_t  port  ) 
    +
    + + + + + +
    +   + + +

    +Stop listening to the specified port. +

    +

    Note:
    Since this function expects the port number in network byte order, a conversion using HTONS() or htons() is necessary.
    +

    +

    Parameters:
    + + +
    port A 16-bit port number in network byte order.
    +
    +
    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00081.html b/doc/html/a00081.html new file mode 100644 index 0000000..ea60ddb --- /dev/null +++ b/doc/html/a00081.html @@ -0,0 +1,149 @@ + + +uIP 0.9: uIP conversion functions + + + + +

    uIP conversion functions
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +These functions can be used for converting between different data formats used by uIP. +

    + + + + + + + + + + + + + +

    Defines

    #define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
     Pack an IP address into a 4-byte array which is used by uIP to represent IP addresses.

    #define HTONS(n)
     Convert 16-bit quantity from host byte order to network byte order.


    Functions

    u16_t htons (u16_t val)
     Convert 16-bit quantity from host byte order to network byte order.

    +


    Define Documentation

    +

    + + + + +
    + + + + + + + +
    #define HTONS  )  +
    +
    + + + + + +
    +   + + +

    +Convert 16-bit quantity from host byte order to network byte order. +

    +This macro is primarily used for converting constants from host byte order to network byte order. For converting variables to network byte order, use the htons() function instead.

    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    #define uip_ipaddraddr,
    addr0,
    addr1,
    addr2,
    addr3   )  +
    +
    + + + + + +
    +   + + +

    +Pack an IP address into a 4-byte array which is used by uIP to represent IP addresses. +

    +Example:

     u16_t ipaddr[2];
    +
    + uip_ipaddr(&ipaddr, 192,168,1,2); 
    +

    +

    Parameters:
    + + + + + + +
    addr A pointer to a 4-byte array that will be filled in with the IP addres.
    addr0 The first octet of the IP address.
    addr1 The second octet of the IP address.
    addr2 The third octet of the IP address.
    addr3 The forth octet of the IP address.
    +
    +
    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    u16_t htons u16_t  val  ) 
    +
    + + + + + +
    +   + + +

    +Convert 16-bit quantity from host byte order to network byte order. +

    +This function is primarily used for converting variables from host byte order to network byte order. For converting constants to network byte order, use the HTONS() macro instead.

    +


    Generated on Tue Oct 7 15:51:43 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00082.html b/doc/html/a00082.html new file mode 100644 index 0000000..531c7e2 --- /dev/null +++ b/doc/html/a00082.html @@ -0,0 +1,213 @@ + + +uIP 0.9: Architecture specific uIP functions + + + + +

    Architecture specific uIP functions
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +The functions in the architecture specific module implement the IP check sum and 32-bit additions.

    +The IP checksum calculation is the most computationally expensive operation in the TCP/IP stack and it therefore pays off to implement this in efficient assembler. The purpose of the uip-arch module is to let the checksum functions to be implemented in architecture specific assembler. +

    + + + + + + + +

    +

    + + + + + + + + + + + + + + + + +

    Files

    file  uip_arch.h
     Declarations of architecture specific functions.


    Functions

    void uip_add32 (u8_t *op32, u16_t op16)
     Carry out a 32-bit addition.

    u16_t uip_chksum (u16_t *buf, u16_t len)
     Calculate the Internet checksum over a buffer.

    u16_t uip_ipchksum (void)
     Calculate the IP header checksum of the packet header in uip_buf.

    u16_t uip_tcpchksum (void)
     Calculate the TCP checksum of the packet in uip_buf and uip_appdata.


    Variables

    +volatile u8_t uip_acc32 [4]
     4-byte array used for the 32-bit sequence number calculations.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    void uip_add32 u8_t op32,
    u16_t  op16
    +
    + + + + + +
    +   + + +

    +Carry out a 32-bit addition. +

    +Because not all architectures for which uIP is intended has native 32-bit arithmetic, uIP uses an external C function for doing the required 32-bit additions in the TCP protocol processing. This function should add the two arguments and place the result in the global variable uip_acc32.

    +

    Note:
    The 32-bit integer pointed to by the op32 parameter and the result in the uip_acc32 variable are in network byte order (big endian).
    +
    Parameters:
    + + + +
    op32 A pointer to a 4-byte array representing a 32-bit integer in network byte order (big endian).
    op16 A 16-bit integer in host byte order.
    +
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    u16_t uip_chksum u16_t buf,
    u16_t  len
    +
    + + + + + +
    +   + + +

    +Calculate the Internet checksum over a buffer. +

    +The Internet checksum is the one's complement of the one's complement sum of all 16-bit words in the buffer.

    +See RFC1071.

    +

    Note:
    This function is not called in the current version of uIP, but future versions might make use of it.
    +
    Parameters:
    + + + +
    buf A pointer to the buffer over which the checksum is to be computed.
    len The length of the buffer over which the checksum is to be computed.
    +
    +
    Returns:
    The Internet checksum of the buffer.
    +
    +

    + + + + +
    + + + + + + + + + + +
    u16_t uip_ipchksum void   ) 
    +
    + + + + + +
    +   + + +

    +Calculate the IP header checksum of the packet header in uip_buf. +

    +The IP header checksum is the Internet checksum of the 20 bytes of the IP header.

    +

    Returns:
    The IP header checksum of the IP header in the uip_buf buffer.
    +
    +

    + + + + +
    + + + + + + + + + + +
    u16_t uip_tcpchksum void   ) 
    +
    + + + + + +
    +   + + +

    +Calculate the TCP checksum of the packet in uip_buf and uip_appdata. +

    +The TCP checksum is the Internet checksum of data contents of the TCP segment, and a pseudo-header as defined in RFC793.

    +

    Note:
    The uip_appdata pointer that points to the packet data may point anywhere in memory, so it is not possible to simply calculate the Internet checksum of the contents of the uip_buf buffer.
    +
    Returns:
    The TCP checksum of the TCP segment in uip_buf and pointed to by uip_appdata.
    +
    +


    Generated on Tue Oct 7 15:51:44 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00083.html b/doc/html/a00083.html new file mode 100644 index 0000000..12db106 --- /dev/null +++ b/doc/html/a00083.html @@ -0,0 +1,190 @@ + + +uIP 0.9: uIP Address Resolution Protocol + + + + +

    uIP Address Resolution Protocol
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +The Address Resolution Protocol ARP is used for mapping between IP addresses and link level addresses such as the Ethernet MAC addresses. ARP uses broadcast queries to ask for the link level address of a known IP address and the host which is configured with the IP address for which the query was meant, will respond with its link level address.

    +

    Note:
    This ARP implementation only supports Ethernet.
    + +

    + + + + + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + + + + + + + + +

    Files

    file  uip_arp.c
     Implementation of the ARP Address Resolution Protocol.

    file  uip_arp.h
     Macros and definitions for the ARP module.


    Data Structures

    struct  uip_eth_addr
     Representation of a 48-bit Ethernet address. More...

    struct  uip_eth_hdr
     The Ethernet header. More...


    Functions

    +void uip_arp_init (void)
     Initialize the ARP module.

    void uip_arp_ipin (void)
     ARP processing for incoming IP packets.

    void uip_arp_arpin (void)
     ARP processing for incoming ARP packets.

    void uip_arp_out (void)
     Prepend Ethernet header to an outbound IP packet and see if we need to send out an ARP request.

    void uip_arp_timer (void)
     Periodic ARP processing function.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    void uip_arp_arpin void   ) 
    +
    + + + + + +
    +   + + +

    +ARP processing for incoming ARP packets. +

    +This function should be called by the device driver when an ARP packet has been received. The function will act differently depending on the ARP packet type: if it is a reply for a request that we previously sent out, the ARP cache will be filled in with the values from the ARP reply. If the incoming ARP packet is an ARP request for our IP address, an ARP reply packet is created and put into the uip_buf[] buffer.

    +When the function returns, the value of the global variable uip_len indicates whether the device driver should send out a packet or not. If uip_len is zero, no packet should be sent. If uip_len is non-zero, it contains the length of the outbound packet that is present in the uip_buf[] buffer.

    +This function expects an ARP packet with a prepended Ethernet header in the uip_buf[] buffer, and the length of the packet in the global variable uip_len.

    +

    + + + + +
    + + + + + + + + + + +
    void uip_arp_ipin void   ) 
    +
    + + + + + +
    +   + + +

    +ARP processing for incoming IP packets. +

    +This function should be called by the device driver when an IP packet has been received. The function will check if the address is in the ARP cache, and if so the ARP cache entry will be refreshed. If no ARP cache entry was found, a new one is created.

    +This function expects an IP packet with a prepended Ethernet header in the uip_buf[] buffer, and the length of the packet in the global variable uip_len.

    +

    + + + + +
    + + + + + + + + + + +
    void uip_arp_out void   ) 
    +
    + + + + + +
    +   + + +

    +Prepend Ethernet header to an outbound IP packet and see if we need to send out an ARP request. +

    +This function should be called before sending out an IP packet. The function checks the destination IP address of the IP packet to see what Ethernet MAC address that should be used as a destination MAC address on the Ethernet.

    +If the destination IP address is in the local network (determined by logical ANDing of netmask and our IP address), the function checks the ARP cache to see if an entry for the destination IP address is found. If so, an Ethernet header is prepended and the function returns. If no ARP cache entry is found for the destination IP address, the packet in the uip_buf[] is replaced by an ARP request packet for the IP address. The IP packet is dropped and it is assumed that they higher level protocols (e.g., TCP) eventually will retransmit the dropped packet.

    +If the destination IP address is not on the local network, the IP address of the default router is used instead.

    +When the function returns, a packet is present in the uip_buf[] buffer, and the length of the packet is in the global variable uip_len.

    +

    + + + + +
    + + + + + + + + + + +
    void uip_arp_timer void   ) 
    +
    + + + + + +
    +   + + +

    +Periodic ARP processing function. +

    +This function performs periodic timer processing in the ARP module and should be called at regular intervals. The recommended interval is 10 seconds between the calls.

    +


    Generated on Tue Oct 7 15:51:44 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00084.html b/doc/html/a00084.html new file mode 100644 index 0000000..56d946c --- /dev/null +++ b/doc/html/a00084.html @@ -0,0 +1,239 @@ + + +uIP 0.9: Serial Line IP (SLIP) protocol + + + + +

    Serial Line IP (SLIP) protocol
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +The SLIP protocol is a very simple way to transmit IP packets over a serial line. It does not provide any framing or error control, and is therefore not very widely used today.

    +This SLIP implementation requires two functions for accessing the serial device: slipdev_char_poll() and slipdev_char_put(). These must be implemented specifically for the system on which the SLIP protocol is to be run. +

    + + + + + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + +

    Files

    file  slipdev.c
     SLIP protocol implementation.

    file  slipdev.h
     SLIP header file.


    Functions

    void slipdev_char_put (u8_t c)
     Put a character on the serial device.

    u8_t slipdev_char_poll (u8_t *c)
     Poll the serial device for a character.

    void slipdev_init (void)
     Initialize the SLIP module.

    void slipdev_send (void)
     Send the packet in the uip_buf and uip_appdata buffers using the SLIP protocol.

    u16_t slipdev_poll (void)
     Poll the SLIP device for an available packet.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    u8_t slipdev_char_poll u8_t c  ) 
    +
    + + + + + +
    +   + + +

    +Poll the serial device for a character. +

    +This function is used by the SLIP implementation to poll the serial device for a character. It must be implemented specifically for the system on which the SLIP implementation is to be run.

    +The function should return immediately regardless if a character is available or not. If a character is available it should be placed at the memory location pointed to by the pointer supplied by the arguement c.

    +

    Parameters:
    + + +
    c A pointer to a byte that is filled in by the function with the received character, if available.
    +
    +
    Return values:
    + + + +
    0 If no character is available.
    Non-zero If a character is available.
    +
    +
    +

    + + + + +
    + + + + + + + + + + +
    void slipdev_char_put u8_t  c  ) 
    +
    + + + + + +
    +   + + +

    +Put a character on the serial device. +

    +This function is used by the SLIP implementation to put a character on the serial device. It must be implemented specifically for the system on which the SLIP implementation is to be run.

    +

    Parameters:
    + + +
    c The character to be put on the serial device.
    +
    +
    +

    + + + + +
    + + + + + + + + + + +
    void slipdev_init void   ) 
    +
    + + + + + +
    +   + + +

    +Initialize the SLIP module. +

    +This function does not initialize the underlying RS232 device, but only the SLIP part.

    +

    + + + + +
    + + + + + + + + + + +
    u16_t slipdev_poll void   ) 
    +
    + + + + + +
    +   + + +

    +Poll the SLIP device for an available packet. +

    +This function will poll the SLIP device to see if a packet is available. It uses a buffer in which all avaliable bytes from the RS232 interface are read into. When a full packet has been read into the buffer, the packet is copied into the uip_buf buffer and the length of the packet is returned.

    +

    Returns:
    The length of the packet placed in the uip_buf buffer, or zero if no packet is available.
    +
    + +

    +Here is the call graph for this function:

    + + + +

    + + + + +
    + + + + + + + + + + +
    void slipdev_send void   ) 
    +
    + + + + + +
    +   + + +

    +Send the packet in the uip_buf and uip_appdata buffers using the SLIP protocol. +

    +The first 40 bytes of the packet (the IP and TCP headers) are read from the uip_buf buffer, and the following bytes (the application data) are read from the uip_appdata buffer.

    + +

    +Here is the call graph for this function:

    + + + +
    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00084_a8_cgraph.png b/doc/html/a00084_a8_cgraph.png new file mode 100644 index 0000000..a5575ec Binary files /dev/null and b/doc/html/a00084_a8_cgraph.png differ diff --git a/doc/html/a00084_a9_cgraph.png b/doc/html/a00084_a9_cgraph.png new file mode 100644 index 0000000..ba1cb6b Binary files /dev/null and b/doc/html/a00084_a9_cgraph.png differ diff --git a/doc/html/a00085.html b/doc/html/a00085.html new file mode 100644 index 0000000..8966abe --- /dev/null +++ b/doc/html/a00085.html @@ -0,0 +1,44 @@ + + +uIP 0.9: Configuration options for uIP + + + + +

    Configuration options for uIP


    Detailed Description

    +uIP is configured using the per-project configuration file "uipopt.h". This file contains all compile-time options for uIP and should be tweaked to match each specific project. The uIP distribution contains a documented example "uipopt.h" that can be copied and modified for each project. +

    + + + + + + + +

    +

    + + + + + + + + + + + + + + + + + + +

    Files

    file  uipopt.h
     Configuration options for uIP.


    Modules

    uIP type definitions
    Static configuration options
    IP configuration options
    UDP configuration options
    TCP configuration options
    ARP configuration options
    General configuration options
    CPU architecture configuration
    Appication specific configurations
    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00086.html b/doc/html/a00086.html new file mode 100644 index 0000000..efd35a0 --- /dev/null +++ b/doc/html/a00086.html @@ -0,0 +1,104 @@ + + +uIP 0.9: uIP type definitions + + + + +

    uIP type definitions
    + +[Configuration options for uIP] +

    +

    + + + + + + + + + + + + +

    Typedefs

    typedef unsigned char u8_t
     The 8-bit unsigned data type.

    typedef unsigned short u16_t
     The 16-bit unsigned data type.

    typedef unsigned short uip_stats_t
     The statistics data type.

    +


    Typedef Documentation

    +

    + + + + +
    + + +
    typedef unsigned short u16_t +
    +
    + + + + + +
    +   + + +

    +The 16-bit unsigned data type. +

    +This may have to be tweaked for your particular compiler. "unsigned short" works for most compilers.

    +

    + + + + +
    + + +
    typedef unsigned char u8_t +
    +
    + + + + + +
    +   + + +

    +The 8-bit unsigned data type. +

    +This may have to be tweaked for your particular compiler. "unsigned char" works for most compilers.

    +

    + + + + +
    + + +
    typedef unsigned short uip_stats_t +
    +
    + + + + + +
    +   + + +

    +The statistics data type. +

    +This datatype determines how high the statistics counters are able to count.

    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00087.html b/doc/html/a00087.html new file mode 100644 index 0000000..5a3ae33 --- /dev/null +++ b/doc/html/a00087.html @@ -0,0 +1,180 @@ + + +uIP 0.9: Static configuration options + + + + +

    Static configuration options
    + +[Configuration options for uIP] +


    Detailed Description

    +These configuration options can be used for setting the IP address settings statically, but only if UIP_FIXEDADDR is set to 1. The configuration options for a specific node includes IP address, netmask and default router as well as the Ethernet address. The netmask, default router and Ethernet address are appliciable only if uIP should be run over Ethernet.

    +All of these should be changed to suit your project. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    #define UIP_FIXEDADDR
     Determines if uIP should use a fixed IP address or not.

    #define UIP_PINGADDRCONF
     Ping IP address asignment.

    +#define UIP_IPADDR0
     The first octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_IPADDR1
     The second octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_IPADDR2
     The third octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_IPADDR3
     The fourth octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK0
     The first octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK1
     The second octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK2
     The third octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_NETMASK3
     The fourth octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR0
     The first octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR1
     The second octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR2
     The third octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    +#define UIP_DRIPADDR3
     The fourth octet of the IP address of the default router, if UIP_FIXEDADDR is 1.

    #define UIP_FIXEDETHADDR
     Specifies if the uIP ARP module should be compiled with a fixed Ethernet MAC address or not.

    +#define UIP_ETHADDR0
     The first octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR1
     The second octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR2
     The third octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR3
     The fourth octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR4
     The fifth octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +#define UIP_ETHADDR5
     The sixth octet of the Ethernet address if UIP_FIXEDETHADDR is 1.

    +


    Define Documentation

    +

    + + + + +
    + + +
    #define UIP_FIXEDADDR +
    +
    + + + + + +
    +   + + +

    +Determines if uIP should use a fixed IP address or not. +

    +If uIP should use a fixed IP address, the settings are set in the uipopt.h file. If not, the macros uip_sethostaddr(), uip_setdraddr() and uip_setnetmask() should be used instead.

    +

    + + + + +
    + + +
    #define UIP_FIXEDETHADDR +
    +
    + + + + + +
    +   + + +

    +Specifies if the uIP ARP module should be compiled with a fixed Ethernet MAC address or not. +

    +If this configuration option is 0, the macro uip_setethaddr() can be used to specify the Ethernet address at run-time.

    +

    + + + + +
    + + +
    #define UIP_PINGADDRCONF +
    +
    + + + + + +
    +   + + +

    +Ping IP address asignment. +

    +uIP uses a "ping" packets for setting its own IP address if this option is set. If so, uIP will start with an empty IP address and the destination IP address of the first incoming "ping" (ICMP echo) packet will be used for setting the hosts IP address.

    +

    Note:
    This works only if UIP_FIXEDADDR is 0.
    +
    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00088.html b/doc/html/a00088.html new file mode 100644 index 0000000..83c83d7 --- /dev/null +++ b/doc/html/a00088.html @@ -0,0 +1,83 @@ + + +uIP 0.9: IP configuration options + + + + +

    IP configuration options
    + +[Configuration options for uIP] +

    +

    + + + + + + + + + + + + +

    Defines

    #define UIP_TTL   255
     The IP TTL (time to live) of IP packets sent by uIP.

    #define UIP_REASSEMBLY
     Turn on support for IP packet reassembly.

    +#define UIP_REASS_MAXAGE   40
     The maximum time an IP fragment should wait in the reassembly buffer before it is dropped.

    +


    Define Documentation

    +

    + + + + +
    + + +
    #define UIP_REASSEMBLY +
    +
    + + + + + +
    +   + + +

    +Turn on support for IP packet reassembly. +

    +uIP supports reassembly of fragmented IP packets. This features requires an additonal amount of RAM to hold the reassembly buffer and the reassembly code size is approximately 700 bytes. The reassembly buffer is of the same size as the uip_buf buffer (configured by UIP_BUFSIZE).

    +

    Note:
    IP packet reassembly is not heavily tested.
    +
    +

    + + + + +
    + + +
    #define UIP_TTL   255 +
    +
    + + + + + +
    +   + + +

    +The IP TTL (time to live) of IP packets sent by uIP. +

    +This should normally not be changed.

    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00089.html b/doc/html/a00089.html new file mode 100644 index 0000000..24d7327 --- /dev/null +++ b/doc/html/a00089.html @@ -0,0 +1,65 @@ + + +uIP 0.9: UDP configuration options + + + + +

    UDP configuration options
    + +[Configuration options for uIP] +


    Detailed Description

    +
    Note:
    The UDP support in uIP is still not entirely complete; there is no support for sending or receiving broadcast or multicast packets, but it works well enough to support a number of vital applications such as DNS queries, though
    + +

    + + + + + + + + + + + + + + + +

    Defines

    +#define UIP_UDP
     Toggles wether UDP support should be compiled in or not.

    #define UIP_UDP_CHECKSUMS
     Toggles if UDP checksums should be used or not.

    +#define UIP_UDP_CONNS
     The maximum amount of concurrent UDP connections.

    +#define UIP_UDP_APPCALL
     The name of the function that should be called when UDP datagrams arrive.

    +


    Define Documentation

    +

    + + + + +
    + + +
    #define UIP_UDP_CHECKSUMS +
    +
    + + + + + +
    +   + + +

    +Toggles if UDP checksums should be used or not. +

    +

    Note:
    Support for UDP checksums is currently not included in uIP, so this option has no function.
    +
    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00090.html b/doc/html/a00090.html new file mode 100644 index 0000000..c21fe00 --- /dev/null +++ b/doc/html/a00090.html @@ -0,0 +1,293 @@ + + +uIP 0.9: TCP configuration options + + + + +

    TCP configuration options
    + +[Configuration options for uIP] +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Defines

    #define UIP_ACTIVE_OPEN
     Determines if support for opening connections from uIP should be compiled in.

    #define UIP_CONNS
     The maximum number of simultaneously open TCP connections.

    #define UIP_LISTENPORTS
     The maximum number of simultaneously listening TCP ports.

    #define UIP_RECEIVE_WINDOW
     The size of the advertised receiver's window.

    #define UIP_URGDATA
     Determines if support for TCP urgent data notification should be compiled in.

    #define UIP_RTO   3
     The initial retransmission timeout counted in timer pulses.

    #define UIP_MAXRTX   8
     The maximum number of times a segment should be retransmitted before the connection should be aborted.

    #define UIP_MAXSYNRTX   3
     The maximum number of times a SYN segment should be retransmitted before a connection request should be deemed to have been unsuccessful.

    #define UIP_TCP_MSS   (UIP_BUFSIZE - UIP_LLH_LEN - 40)
     The TCP maximum segment size.

    #define UIP_TIME_WAIT_TIMEOUT   120
     How long a connection should stay in the TIME_WAIT state.

    +


    Define Documentation

    +

    + + + + +
    + + +
    #define UIP_ACTIVE_OPEN +
    +
    + + + + + +
    +   + + +

    +Determines if support for opening connections from uIP should be compiled in. +

    +If the applications that are running on top of uIP for this project do not need to open outgoing TCP connections, this configration option can be turned off to reduce the code size of uIP.

    +

    + + + + +
    + + +
    #define UIP_CONNS +
    +
    + + + + + +
    +   + + +

    +The maximum number of simultaneously open TCP connections. +

    +Since the TCP connections are statically allocated, turning this configuration knob down results in less RAM used. Each TCP connection requires approximatly 30 bytes of memory.

    +

    + + + + +
    + + +
    #define UIP_LISTENPORTS +
    +
    + + + + + +
    +   + + +

    +The maximum number of simultaneously listening TCP ports. +

    +Each listening TCP port requires 2 bytes of memory.

    +

    + + + + +
    + + +
    #define UIP_MAXRTX   8 +
    +
    + + + + + +
    +   + + +

    +The maximum number of times a segment should be retransmitted before the connection should be aborted. +

    +This should not be changed.

    +

    + + + + +
    + + +
    #define UIP_MAXSYNRTX   3 +
    +
    + + + + + +
    +   + + +

    +The maximum number of times a SYN segment should be retransmitted before a connection request should be deemed to have been unsuccessful. +

    +This should not need to be changed.

    +

    + + + + +
    + + +
    #define UIP_RECEIVE_WINDOW +
    +
    + + + + + +
    +   + + +

    +The size of the advertised receiver's window. +

    +Should be set low (i.e., to the size of the uip_buf buffer) is the application is slow to process incoming data, or high (32768 bytes) if the application processes data quickly.

    +

    + + + + +
    + + +
    #define UIP_RTO   3 +
    +
    + + + + + +
    +   + + +

    +The initial retransmission timeout counted in timer pulses. +

    +This should not be changed.

    +

    + + + + +
    + + +
    #define UIP_TCP_MSS   (UIP_BUFSIZE - UIP_LLH_LEN - 40) +
    +
    + + + + + +
    +   + + +

    +The TCP maximum segment size. +

    +This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40.

    +

    + + + + +
    + + +
    #define UIP_TIME_WAIT_TIMEOUT   120 +
    +
    + + + + + +
    +   + + +

    +How long a connection should stay in the TIME_WAIT state. +

    +This configiration option has no real implication, and it should be left untouched.

    +

    + + + + +
    + + +
    #define UIP_URGDATA +
    +
    + + + + + +
    +   + + +

    +Determines if support for TCP urgent data notification should be compiled in. +

    +Urgent data (out-of-band data) is a rarely used TCP feature that very seldom would be required.

    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00091.html b/doc/html/a00091.html new file mode 100644 index 0000000..ec24111 --- /dev/null +++ b/doc/html/a00091.html @@ -0,0 +1,77 @@ + + +uIP 0.9: ARP configuration options + + + + +

    ARP configuration options
    + +[Configuration options for uIP] +

    +

    + + + + + + + + + +

    Defines

    #define UIP_ARPTAB_SIZE
     The size of the ARP table.

    #define UIP_ARP_MAXAGE   120
     The maxium age of ARP table entries measured in 10ths of seconds.

    +


    Define Documentation

    +

    + + + + +
    + + +
    #define UIP_ARP_MAXAGE   120 +
    +
    + + + + + +
    +   + + +

    +The maxium age of ARP table entries measured in 10ths of seconds. +

    +An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD default).

    +

    + + + + +
    + + +
    #define UIP_ARPTAB_SIZE +
    +
    + + + + + +
    +   + + +

    +The size of the ARP table. +

    +This option should be set to a larger value if this uIP node will have many connections from the local network.

    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00092.html b/doc/html/a00092.html new file mode 100644 index 0000000..68a1059 --- /dev/null +++ b/doc/html/a00092.html @@ -0,0 +1,167 @@ + + +uIP 0.9: General configuration options + + + + +

    General configuration options
    + +[Configuration options for uIP] +

    +

    + + + + + + + + + + + + + + + + + + + +

    Defines

    #define UIP_BUFSIZE
     The size of the uIP packet buffer.

    #define UIP_STATISTICS
     Determines if statistics support should be compiled in.

    #define UIP_LOGGING
     Determines if logging of certain events should be compiled in.

    #define UIP_LLH_LEN
     The link level header length.


    Functions

    void uip_log (char *msg)
     Print out a uIP log message.

    +


    Define Documentation

    +

    + + + + +
    + + +
    #define UIP_BUFSIZE +
    +
    + + + + + +
    +   + + +

    +The size of the uIP packet buffer. +

    +The uIP packet buffer should not be smaller than 60 bytes, and does not need to be larger than 1500 bytes. Lower size results in lower TCP throughput, larger size results in higher TCP throughput.

    +

    + + + + +
    + + +
    #define UIP_LLH_LEN +
    +
    + + + + + +
    +   + + +

    +The link level header length. +

    +This is the offset into the uip_buf where the IP header can be found. For Ethernet, this should be set to 14. For SLIP, this should be set to 0.

    +

    + + + + +
    + + +
    #define UIP_LOGGING +
    +
    + + + + + +
    +   + + +

    +Determines if logging of certain events should be compiled in. +

    +This is useful mostly for debugging. The function uip_log() must be implemented to suit the architecture of the project, if logging is turned on.

    +

    + + + + +
    + + +
    #define UIP_STATISTICS +
    +
    + + + + + +
    +   + + +

    +Determines if statistics support should be compiled in. +

    +The statistics is useful for debugging and to show the user.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    void uip_log char *  msg  ) 
    +
    + + + + + +
    +   + + +

    +Print out a uIP log message. +

    +This function must be implemented by the module that uses uIP, and is called by uIP whenever a log message is generated.

    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00093.html b/doc/html/a00093.html new file mode 100644 index 0000000..1d115ab --- /dev/null +++ b/doc/html/a00093.html @@ -0,0 +1,51 @@ + + +uIP 0.9: CPU architecture configuration + + + + +

    CPU architecture configuration
    + +[Configuration options for uIP] +


    Detailed Description

    +The CPU architecture configuration is where the endianess of the CPU on which uIP is to be run is specified. Most CPUs today are little endian, and the most notable exception are the Motorolas which are big endian. The BYTE_ORDER macro should be changed to reflect the CPU architecture on which uIP is to be run. +

    + + + + + + +

    Defines

    #define BYTE_ORDER
     The byte order of the CPU architecture on which uIP is to be run.

    +


    Define Documentation

    +

    + + + + +
    + + +
    #define BYTE_ORDER +
    +
    + + + + + +
    +   + + +

    +The byte order of the CPU architecture on which uIP is to be run. +

    +This option can be either BIG_ENDIAN (Motorola byte order) or LITTLE_ENDIAN (Intel byte order).

    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00094.html b/doc/html/a00094.html new file mode 100644 index 0000000..2e6f3c2 --- /dev/null +++ b/doc/html/a00094.html @@ -0,0 +1,44 @@ + + +uIP 0.9: Appication specific configurations + + + + +

    Appication specific configurations
    + +[Configuration options for uIP] +


    Detailed Description

    +An uIP application is implemented using a single application function that is called by uIP whenever a TCP/IP event occurs. The name of this function must be registered with uIP at compile time using the UIP_APPCALL definition.

    +uIP applications can store the application state within the uip_conn structure by specifying the size of the application structure with the UIP_APPSTATE_SIZE macro.

    +The file containing the definitions must be included in the uipopt.h file.

    +The following example illustrates how this can look.

    void httpd_appcall(void);
    +#define UIP_APPCALL     httpd_appcall
    +
    +struct httpd_state {
    +  u8_t state; 
    +  u16_t count;
    +  char *dataptr;
    +  char *script;
    +};
    +#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state))
    +
    +

    + + + + + + + + + +

    Defines

    +#define UIP_APPCALL   smtp_appcall
     The name of the application function that uIP should call in response to TCP/IP events.

    +#define UIP_APPSTATE_SIZE   (sizeof(struct smtp_state))
     The size of the application state that is to be stored in the uip_conn structure.

    +


    Generated on Tue Oct 7 15:51:45 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00095.html b/doc/html/a00095.html new file mode 100644 index 0000000..2d49f8e --- /dev/null +++ b/doc/html/a00095.html @@ -0,0 +1,447 @@ + + +uIP 0.9: Web client + + + + +

    Web client
    + +[Example applications] +


    Detailed Description

    +This example shows a HTTP client that is able to download web pages and files from web servers. It requires a number of callback functions to be implemented by the module that utilizes the code: webclient_datahandler(), webclient_connected(), webclient_timedout(), webclient_aborted(), webclient_closed(). +

    + + + + + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Files

    file  webclient.c
     Implementation of the HTTP client.

    file  webclient.h
     Header file for the HTTP client.


    Functions

    void webclient_datahandler (char *data, u16_t len)
     Callback function that is called from the webclient code when HTTP data has been received.

    void webclient_connected (void)
     Callback function that is called from the webclient code when the HTTP connection has been connected to the web server.

    void webclient_timedout (void)
     Callback function that is called from the webclient code if the HTTP connection to the web server has timed out.

    void webclient_aborted (void)
     Callback function that is called from the webclient code if the HTTP connection to the web server has been aborted by the web server.

    void webclient_closed (void)
     Callback function that is called from the webclient code when the HTTP connection to the web server has been closed.

    +void webclient_init (void)
     Initialize the webclient module.

    unsigned char webclient_get (char *host, u16_t port, char *file)
     Open an HTTP connection to a web server and ask for a file using the GET method.

    +void webclient_close (void)
     Close the currently open HTTP connection.

    char * webclient_mimetype (void)
     Obtain the MIME type of the current HTTP data stream.

    char * webclient_filename (void)
     Obtain the filename of the current HTTP data stream.

    char * webclient_hostname (void)
     Obtain the hostname of the current HTTP data stream.

    unsigned short webclient_port (void)
     Obtain the port number of the current HTTP data stream.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    void webclient_aborted void   ) 
    +
    + + + + + +
    +   + + +

    +Callback function that is called from the webclient code if the HTTP connection to the web server has been aborted by the web server. +

    +This function must be implemented by the module that uses the webclient code.

    +

    + + + + +
    + + + + + + + + + + +
    void webclient_closed void   ) 
    +
    + + + + + +
    +   + + +

    +Callback function that is called from the webclient code when the HTTP connection to the web server has been closed. +

    +This function must be implemented by the module that uses the webclient code.

    +

    + + + + +
    + + + + + + + + + + +
    void webclient_connected void   ) 
    +
    + + + + + +
    +   + + +

    +Callback function that is called from the webclient code when the HTTP connection has been connected to the web server. +

    +This function must be implemented by the module that uses the webclient code.

    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    void webclient_datahandler char *  data,
    u16_t  len
    +
    + + + + + +
    +   + + +

    +Callback function that is called from the webclient code when HTTP data has been received. +

    +This function must be implemented by the module that uses the webclient code. The function is called from the webclient module when HTTP data has been received. The function is not called when HTTP headers are received, only for the actual data.

    +

    Note:
    This function is called many times, repetedly, when data is being received, and not once when all data has been received.
    +
    Parameters:
    + + + +
    data A pointer to the data that has been received.
    len The length of the data that has been received.
    +
    +
    +

    + + + + +
    + + + + + + + + + + +
    char* webclient_filename void   ) 
    +
    + + + + + +
    +   + + +

    +Obtain the filename of the current HTTP data stream. +

    +The filename of an HTTP request may be changed by the web server, and may therefore not be the same as when the original GET request was made with webclient_get(). This function is used for obtaining the current filename.

    +

    Returns:
    A pointer to the current filename.
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    unsigned char webclient_get char *  host,
    u16_t  port,
    char *  file
    +
    + + + + + +
    +   + + +

    +Open an HTTP connection to a web server and ask for a file using the GET method. +

    +This function opens an HTTP connection to the specified web server and requests the specified file using the GET method. When the HTTP connection has been connected, the webclient_connected() callback function is called and when the HTTP data arrives the webclient_datahandler() callback function is called.

    +The callback function webclient_timedout() is called if the web server could not be contacted, and the webclient_aborted() callback function is called if the HTTP connection is aborted by the web server.

    +When the HTTP request has been completed and the HTTP connection is closed, the webclient_closed() callback function will be called.

    +

    Note:
    If the function is passed a host name, it must already be in the resolver cache in order for the function to connect to the web server. It is therefore up to the calling module to implement the resolver calls and the signal handler used for reporting a resolv query answer.
    +
    Parameters:
    + + + + +
    host A pointer to a string containing either a host name or a numerical IP address in dotted decimal notation (e.g., 192.168.23.1).
    port The port number to which to connect, in host byte order.
    file A pointer to the name of the file to get.
    +
    +
    Return values:
    + + + +
    0 if the host name could not be found in the cache, or if a TCP connection could not be created.
    1 if the connection was initiated.
    +
    +
    + +

    +Here is the call graph for this function:

    + + + + + +

    + + + + +
    + + + + + + + + + + +
    char* webclient_hostname void   ) 
    +
    + + + + + +
    +   + + +

    +Obtain the hostname of the current HTTP data stream. +

    +The hostname of the web server of an HTTP request may be changed by the web server, and may therefore not be the same as when the original GET request was made with webclient_get(). This function is used for obtaining the current hostname.

    +

    Returns:
    A pointer to the current hostname.
    +
    +

    + + + + +
    + + + + + + + + + + +
    char* webclient_mimetype void   ) 
    +
    + + + + + +
    +   + + +

    +Obtain the MIME type of the current HTTP data stream. +

    +

    Returns:
    A pointer to a string contaning the MIME type. The string may be empty if no MIME type was reported by the web server.
    +
    +

    + + + + +
    + + + + + + + + + + +
    unsigned short webclient_port void   ) 
    +
    + + + + + +
    +   + + +

    +Obtain the port number of the current HTTP data stream. +

    +The port number of an HTTP request may be changed by the web server, and may therefore not be the same as when the original GET request was made with webclient_get(). This function is used for obtaining the current port number.

    +

    Returns:
    The port number of the current HTTP data stream, in host byte order.
    +
    +

    + + + + +
    + + + + + + + + + + +
    void webclient_timedout void   ) 
    +
    + + + + + +
    +   + + +

    +Callback function that is called from the webclient code if the HTTP connection to the web server has timed out. +

    +This function must be implemented by the module that uses the webclient code.

    +


    Generated on Tue Oct 7 15:51:46 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00095_a20_cgraph.png b/doc/html/a00095_a20_cgraph.png new file mode 100644 index 0000000..7322043 Binary files /dev/null and b/doc/html/a00095_a20_cgraph.png differ diff --git a/doc/html/a00096.html b/doc/html/a00096.html new file mode 100644 index 0000000..7ba6d3e --- /dev/null +++ b/doc/html/a00096.html @@ -0,0 +1,206 @@ + + +uIP 0.9: SMTP E-mail sender + + + + +

    SMTP E-mail sender
    + +[Example applications] +


    Detailed Description

    +The Simple Mail Transfer Protocol (SMTP) as defined by RFC821 is the standard way of sending and transfering e-mail on the Internet. This simple example implementation is intended as an example of how to implement protocols in uIP, and is able to send out e-mail but has not been extensively tested. +

    + + + + + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + +

    Files

    file  smtp.c
     SMTP example implementation.

    file  smtp.h
     SMTP header file.


    Defines

    +#define SMTP_ERR_OK   0
     Error number that signifies a non-error condition.


    Functions

    void smtp_done (unsigned char error)
     Callback function that is called when an e-mail transmission is done.

    void smtp_configure (char *localhostname, u16_t *smtpserver)
     Specificy an SMTP server and hostname.

    unsigned char smtp_send (char *to, char *from, char *subject, char *msg, u16_t msglen)
     Send an e-mail.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    void smtp_configure char *  lhostname,
    u16_t server
    +
    + + + + + +
    +   + + +

    +Specificy an SMTP server and hostname. +

    +This function is used to configure the SMTP module with an SMTP server and the hostname of the host.

    +

    Parameters:
    + + + +
    lhostname The hostname of the uIP host.
    server A pointer to a 4-byte array representing the IP address of the SMTP server to be configured.
    +
    +
    +

    + + + + +
    + + + + + + + + + + +
    void smtp_done unsigned char  error  ) 
    +
    + + + + + +
    +   + + +

    +Callback function that is called when an e-mail transmission is done. +

    +This function must be implemented by the module that uses the SMTP module.

    +

    Parameters:
    + + +
    error The number of the error if an error occured, or SMTP_ERR_OK.
    +
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    unsigned char smtp_send char *  to,
    char *  from,
    char *  subject,
    char *  msg,
    u16_t  msglen
    +
    + + + + + +
    +   + + +

    +Send an e-mail. +

    +

    Parameters:
    + + + + + + +
    to The e-mail address of the receiver of the e-mail.
    from The e-mail address of the sender of the e-mail.
    subject The subject of the e-mail.
    msg The actual e-mail message.
    msglen The length of the e-mail message.
    +
    +
    + +

    +Here is the call graph for this function:

    + + + +
    Generated on Tue Oct 7 15:51:47 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00096_a23_cgraph.png b/doc/html/a00096_a23_cgraph.png new file mode 100644 index 0000000..f035d2b Binary files /dev/null and b/doc/html/a00096_a23_cgraph.png differ diff --git a/doc/html/a00097.html b/doc/html/a00097.html new file mode 100644 index 0000000..3bc3bc2 --- /dev/null +++ b/doc/html/a00097.html @@ -0,0 +1,344 @@ + + +uIP 0.9: Telnet server + + + + +

    Telnet server
    + +[Example applications] +


    Detailed Description

    +The uIP telnet server provides a command based interface to uIP. It allows using the "telnet" application to access uIP, and implements the required telnet option negotiation.

    +The code is structured in a way which makes it possible to add commands without having to rewrite the main telnet code. The main telnet code calls two callback functions, telnetd_connected() and telnetd_input(), when a telnet connection has been established and when a line of text arrives on a telnet connection. These two functions can be implemented in a way which suits the particular application or environment in which the uIP system is intended to be run.

    +The uIP distribution contains an example telnet shell implementation that provides a basic set of commands. +

    + + + + + + + +

    +

    + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Files

    file  telnetd-shell.c
     An example telnet server shell.

    file  telnetd.c
     Implementation of the Telnet server.

    file  telnetd.h
     Header file for the telnet server.


    Data Structures

    struct  telnetd_state
     A telnet connection structure. More...


    Defines

    +#define TELNETD_LINELEN
     The maximum length of a telnet line.

    +#define TELNETD_NUMLINES
     The number of output lines being buffered for all telnet connections.


    Functions

    void telnetd_connected (struct telnetd_state *s)
     Callback function that is called when a telnet connection has been established.

    void telnetd_input (struct telnetd_state *s, char *cmd)
     Callback function that is called when a line of text has arrived on a telnet connection.

    void telnetd_close (struct telnetd_state *s)
     Close a telnet session.

    void telnetd_output (struct telnetd_state *s, char *s1, char *s2)
     Print out a string on a telnet connection.

    void telnetd_prompt (struct telnetd_state *s, char *str)
     Print a prompt on a telnet connection.

    void telnetd_init (void)
     Initialize the telnet server.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    void telnetd_close struct telnetd_state s  ) 
    +
    + + + + + +
    +   + + +

    +Close a telnet session. +

    +This function can be called from a telnet command in order to close the connection.

    +

    Parameters:
    + + +
    s The connection which is to be closed.
    +
    +
    +

    + + + + +
    + + + + + + + + + + +
    void telnetd_connected struct telnetd_state s  ) 
    +
    + + + + + +
    +   + + +

    +Callback function that is called when a telnet connection has been established. +

    +

    Parameters:
    + + +
    s The telnet connection.
    +
    +
    + +

    +Here is the call graph for this function:

    + + + + +

    + + + + +
    + + + + + + + + + + +
    void telnetd_init void   ) 
    +
    + + + + + +
    +   + + +

    +Initialize the telnet server. +

    +This function will perform the necessary initializations and start listening on TCP port 23.

    + +

    +Here is the call graph for this function:

    + + + + +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    void telnetd_input struct telnetd_state s,
    char *  cmd
    +
    + + + + + +
    +   + + +

    +Callback function that is called when a line of text has arrived on a telnet connection. +

    +

    Parameters:
    + + + +
    s The telnet connection.
    cmd The line of text.
    +
    +
    + +

    +Here is the call graph for this function:

    + + + +

    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    void telnetd_output struct telnetd_state s,
    char *  str1,
    char *  str2
    +
    + + + + + +
    +   + + +

    +Print out a string on a telnet connection. +

    +This function can be called from a telnet command parser in order to print out a string of text on the connection. The two strings given as arguments to the function will be concatenated, a carrige return and a new line character will be added, and the line is sent.

    +

    Parameters:
    + + + + +
    s The telnet connection.
    str1 The first string.
    str2 The second string.
    +
    +
    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    void telnetd_prompt struct telnetd_state s,
    char *  str
    +
    + + + + + +
    +   + + +

    +Print a prompt on a telnet connection. +

    +This function can be called by the telnet command shell in order to print out a command prompt.

    +

    Parameters:
    + + + +
    s A telnet connection.
    str The command prompt.
    +
    +
    +


    Generated on Tue Oct 7 15:51:49 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00097_a22_cgraph.png b/doc/html/a00097_a22_cgraph.png new file mode 100644 index 0000000..8343802 Binary files /dev/null and b/doc/html/a00097_a22_cgraph.png differ diff --git a/doc/html/a00097_a7_cgraph.png b/doc/html/a00097_a7_cgraph.png new file mode 100644 index 0000000..313b8ba Binary files /dev/null and b/doc/html/a00097_a7_cgraph.png differ diff --git a/doc/html/a00097_a8_cgraph.png b/doc/html/a00097_a8_cgraph.png new file mode 100644 index 0000000..c966a62 Binary files /dev/null and b/doc/html/a00097_a8_cgraph.png differ diff --git a/doc/html/a00098.html b/doc/html/a00098.html new file mode 100644 index 0000000..1ccf95b --- /dev/null +++ b/doc/html/a00098.html @@ -0,0 +1,174 @@ + + +uIP 0.9: Web server + + + + +

    Web server
    + +[Example applications] +


    Detailed Description

    +The uIP web server is a very simplistic implementation of an HTTP server. It can serve web pages and files from a read-only ROM filesystem, and provides a very small scripting language.

    +The script language is very simple and works as follows. Each script line starts with a command character, either "i", "t", "c", "#" or ".". The "i" command tells the script interpreter to "include" a file from the virtual file system and output it to the web browser. The "t" command should be followed by a line of text that is to be output to the browser. The "c" command is used to call one of the C functions from the httpd-cgi.c file. A line that starts with a "#" is ignored (i.e., the "#" denotes a comment), and the "." denotes the last script line.

    +The script that produces the file statistics page looks somewhat like this:

    +

    i /header.html
    +t <h1>File statistics</h1><br><table width="100%">
    +t <tr><td><a href="/index.html">/index.html</a></td><td>
    +c a /index.html
    +t </td></tr> <tr><td><a href="/cgi/files">/cgi/files</a></td><td>
    +c a /cgi/files
    +t </td></tr> <tr><td><a href="/cgi/tcp">/cgi/tcp</a></td><td>
    +c a /cgi/tcp
    +t </td></tr> <tr><td><a href="/404.html">/404.html</a></td><td>
    +c a /404.html
    +t </td></tr></table>
    +i /footer.plain
    +.
    +
    +

    + + + + + + + +

    +

    + + + +

    +

    + + + +

    +

    + + + +

    +

    + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + + + +

    Files

    file  cgi.c
     HTTP server script language C functions file.

    file  cgi.h
     HTTP script language header file.

    file  fs.c
     HTTP server read-only file system code.

    file  fs.h
     HTTP server read-only file system header file.

    file  httpd.c
     HTTP server.

    file  httpd.h
     HTTP server header file.


    Data Structures

    struct  fs_file
     An open file in the read-only file system. More...


    Functions

    void httpd_init (void)
     Initialize the web server.

    int fs_open (const char *name, struct fs_file *file)
     Open a file in the read-only file system.

    +void fs_init (void)
     Initialize the read-only file system.


    Variables

    +cgifunction cgitab []
     A table containing pointers to C functions that can be called from a web server script.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    int fs_open const char *  name,
    struct fs_file file
    +
    + + + + + +
    +   + + +

    +Open a file in the read-only file system. +

    +

    Parameters:
    + + + +
    name The name of the file.
    file The file pointer, which must be allocated by caller and will be filled in by the function.
    +
    +
    +

    + + + + +
    + + + + + + + + + + +
    void httpd_init void   ) 
    +
    + + + + + +
    +   + + +

    +Initialize the web server. +

    +Starts to listen for incoming connection requests on TCP port 80.

    + +

    +Here is the call graph for this function:

    + + + + +
    Generated on Tue Oct 7 15:51:50 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00098_a27_cgraph.png b/doc/html/a00098_a27_cgraph.png new file mode 100644 index 0000000..8662091 Binary files /dev/null and b/doc/html/a00098_a27_cgraph.png differ diff --git a/doc/html/a00099.html b/doc/html/a00099.html new file mode 100644 index 0000000..73021c8 --- /dev/null +++ b/doc/html/a00099.html @@ -0,0 +1,245 @@ + + +uIP 0.9: uIP hostname resolver functions + + + + +

    uIP hostname resolver functions
    + +[The uIP TCP/IP stack] +


    Detailed Description

    +The uIP DNS resolver functions are used to lookup a hostname and map it to a numerical IP address. It maintains a list of resolved hostnames that can be queried with the resolv_lookup() function. New hostnames can be resolved using the resolv_query() function.

    +When a hostname has been resolved (or found to be non-existant), the resolver code calls a callback function called resolv_found() that must be implemented by the module that uses the resolver. +

    + + + + + + + +

    +

    + + + +

    +

    + + + + + + + + + + + + + + + + + + +

    Files

    file  resolv.c
     DNS host name to IP address resolver.

    file  resolv.h
     DNS resolver code header file.


    Functions

    void resolv_found (char *name, u16_t *ipaddr)
     Callback function which is called when a hostname is found.

    void resolv_conf (u16_t *dnsserver)
     Configure which DNS server to use for queries.

    u16_tresolv_getserver (void)
     Obtain the currently configured DNS server.

    +void resolv_init (void)
     Initalize the resolver.

    u16_tresolv_lookup (char *name)
     Look up a hostname in the array of known hostnames.

    void resolv_query (char *name)
     Queues a name so that a question for the name will be sent out.

    +


    Function Documentation

    +

    + + + + +
    + + + + + + + + + + +
    void resolv_conf u16_t dnsserver  ) 
    +
    + + + + + +
    +   + + +

    +Configure which DNS server to use for queries. +

    +

    Parameters:
    + + +
    dnsserver A pointer to a 4-byte representation of the IP address of the DNS server to be configured.
    +
    +
    + +

    +Here is the call graph for this function:

    + + + +

    + + + + +
    + + + + + + + + + + + + + + + + + + + +
    void resolv_found char *  name,
    u16_t ipaddr
    +
    + + + + + +
    +   + + +

    +Callback function which is called when a hostname is found. +

    +This function must be implemented by the module that uses the DNS resolver. It is called when a hostname is found, or when a hostname was not found.

    +

    Parameters:
    + + + +
    name A pointer to the name that was looked up.
    ipaddr A pointer to a 4-byte array containing the IP address of the hostname, or NULL if the hostname could not be found.
    +
    +
    +

    + + + + +
    + + + + + + + + + + +
    u16_t* resolv_getserver void   ) 
    +
    + + + + + +
    +   + + +

    +Obtain the currently configured DNS server. +

    +

    Returns:
    A pointer to a 4-byte representation of the IP address of the currently configured DNS server or NULL if no DNS server has been configured.
    +
    +

    + + + + +
    + + + + + + + + + + +
    u16_t* resolv_lookup char *  name  ) 
    +
    + + + + + +
    +   + + +

    +Look up a hostname in the array of known hostnames. +

    +

    Note:
    This function only looks in the internal array of known hostnames, it does not send out a query for the hostname if none was found. The function resolv_query() can be used to send a query for a hostname.
    +
    Returns:
    A pointer to a 4-byte representation of the hostname's IP address, or NULL if the hostname was not found in the array of hostnames.
    +
    +

    + + + + +
    + + + + + + + + + + +
    void resolv_query char *  name  ) 
    +
    + + + + + +
    +   + + +

    +Queues a name so that a question for the name will be sent out. +

    +

    Parameters:
    + + +
    name The hostname that is to be queried.
    +
    +
    +


    Generated on Tue Oct 7 15:51:51 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/a00099_a29_cgraph.png b/doc/html/a00099_a29_cgraph.png new file mode 100644 index 0000000..c528ba8 Binary files /dev/null and b/doc/html/a00099_a29_cgraph.png differ diff --git a/doc/html/a00103.png b/doc/html/a00103.png new file mode 100644 index 0000000..daf663e Binary files /dev/null and b/doc/html/a00103.png differ diff --git a/doc/html/a00104.png b/doc/html/a00104.png new file mode 100644 index 0000000..9ebddd4 Binary files /dev/null and b/doc/html/a00104.png differ diff --git a/doc/html/a00105.png b/doc/html/a00105.png new file mode 100644 index 0000000..3d468fd Binary files /dev/null and b/doc/html/a00105.png differ diff --git a/doc/html/a00106.png b/doc/html/a00106.png new file mode 100644 index 0000000..d3a016b Binary files /dev/null and b/doc/html/a00106.png differ diff --git a/doc/html/a00107.png b/doc/html/a00107.png new file mode 100644 index 0000000..445c7fd Binary files /dev/null and b/doc/html/a00107.png differ diff --git a/doc/html/a00108.png b/doc/html/a00108.png new file mode 100644 index 0000000..0f765f5 Binary files /dev/null and b/doc/html/a00108.png differ diff --git a/doc/html/a00109.png b/doc/html/a00109.png new file mode 100644 index 0000000..9f5659f Binary files /dev/null and b/doc/html/a00109.png differ diff --git a/doc/html/a00110.png b/doc/html/a00110.png new file mode 100644 index 0000000..297bc21 Binary files /dev/null and b/doc/html/a00110.png differ diff --git a/doc/html/a00111.png b/doc/html/a00111.png new file mode 100644 index 0000000..c8a3ed4 Binary files /dev/null and b/doc/html/a00111.png differ diff --git a/doc/html/a00112.png b/doc/html/a00112.png new file mode 100644 index 0000000..bddda68 Binary files /dev/null and b/doc/html/a00112.png differ diff --git a/doc/html/a00113.png b/doc/html/a00113.png new file mode 100644 index 0000000..b611625 Binary files /dev/null and b/doc/html/a00113.png differ diff --git a/doc/html/a00114.png b/doc/html/a00114.png new file mode 100644 index 0000000..7601a2f Binary files /dev/null and b/doc/html/a00114.png differ diff --git a/doc/html/a00115.png b/doc/html/a00115.png new file mode 100644 index 0000000..4c612cd Binary files /dev/null and b/doc/html/a00115.png differ diff --git a/doc/html/a00116.png b/doc/html/a00116.png new file mode 100644 index 0000000..c9b2e21 Binary files /dev/null and b/doc/html/a00116.png differ diff --git a/doc/html/a00117.png b/doc/html/a00117.png new file mode 100644 index 0000000..30892dd Binary files /dev/null and b/doc/html/a00117.png differ diff --git a/doc/html/a00118.png b/doc/html/a00118.png new file mode 100644 index 0000000..55440eb Binary files /dev/null and b/doc/html/a00118.png differ diff --git a/doc/html/a00119.png b/doc/html/a00119.png new file mode 100644 index 0000000..9a32545 Binary files /dev/null and b/doc/html/a00119.png differ diff --git a/doc/html/a00120.png b/doc/html/a00120.png new file mode 100644 index 0000000..67f08c1 Binary files /dev/null and b/doc/html/a00120.png differ diff --git a/doc/html/a00121.png b/doc/html/a00121.png new file mode 100644 index 0000000..48d4e72 Binary files /dev/null and b/doc/html/a00121.png differ diff --git a/doc/html/a00122.png b/doc/html/a00122.png new file mode 100644 index 0000000..9eb8b18 Binary files /dev/null and b/doc/html/a00122.png differ diff --git a/doc/html/a00123.png b/doc/html/a00123.png new file mode 100644 index 0000000..c6528d5 Binary files /dev/null and b/doc/html/a00123.png differ diff --git a/doc/html/a00124.png b/doc/html/a00124.png new file mode 100644 index 0000000..6fa3b2c Binary files /dev/null and b/doc/html/a00124.png differ diff --git a/doc/html/a00125.png b/doc/html/a00125.png new file mode 100644 index 0000000..290091a Binary files /dev/null and b/doc/html/a00125.png differ diff --git a/doc/html/a00126.png b/doc/html/a00126.png new file mode 100644 index 0000000..95852f4 Binary files /dev/null and b/doc/html/a00126.png differ diff --git a/doc/html/a00127.png b/doc/html/a00127.png new file mode 100644 index 0000000..d7d2351 Binary files /dev/null and b/doc/html/a00127.png differ diff --git a/doc/html/a00128.png b/doc/html/a00128.png new file mode 100644 index 0000000..053eff8 Binary files /dev/null and b/doc/html/a00128.png differ diff --git a/doc/html/a00129.png b/doc/html/a00129.png new file mode 100644 index 0000000..b3962f5 Binary files /dev/null and b/doc/html/a00129.png differ diff --git a/doc/html/a00130.png b/doc/html/a00130.png new file mode 100644 index 0000000..ca75f1f Binary files /dev/null and b/doc/html/a00130.png differ diff --git a/doc/html/a00131.png b/doc/html/a00131.png new file mode 100644 index 0000000..25b2c82 Binary files /dev/null and b/doc/html/a00131.png differ diff --git a/doc/html/a00132.png b/doc/html/a00132.png new file mode 100644 index 0000000..5081ad3 Binary files /dev/null and b/doc/html/a00132.png differ diff --git a/doc/html/a00133.png b/doc/html/a00133.png new file mode 100644 index 0000000..20918b9 Binary files /dev/null and b/doc/html/a00133.png differ diff --git a/doc/html/a00134.png b/doc/html/a00134.png new file mode 100644 index 0000000..3af688b Binary files /dev/null and b/doc/html/a00134.png differ diff --git a/doc/html/a00135.png b/doc/html/a00135.png new file mode 100644 index 0000000..3123563 Binary files /dev/null and b/doc/html/a00135.png differ diff --git a/doc/html/a00136.png b/doc/html/a00136.png new file mode 100644 index 0000000..38b503c Binary files /dev/null and b/doc/html/a00136.png differ diff --git a/doc/html/a00137.png b/doc/html/a00137.png new file mode 100644 index 0000000..34ee2f2 Binary files /dev/null and b/doc/html/a00137.png differ diff --git a/doc/html/annotated.html b/doc/html/annotated.html new file mode 100644 index 0000000..905c81d --- /dev/null +++ b/doc/html/annotated.html @@ -0,0 +1,22 @@ + + +uIP 0.9: Annotated Index + + + + +

    uIP 0.9 Data Structures

    Here are the data structures with brief descriptions: + + + + + + + +
    fs_fileAn open file in the read-only file system
    telnetd_stateA telnet connection structure
    uip_connRepresentation of a uIP TCP connection
    uip_eth_addrRepresentation of a 48-bit Ethernet address
    uip_eth_hdrThe Ethernet header
    uip_statsThe structure holding the TCP/IP statistics that are gathered if UIP_STATISTICS is set to 1
    uip_udp_connRepresentation of a uIP UDP connection
    +
    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/classes.html b/doc/html/classes.html new file mode 100644 index 0000000..96e6f78 --- /dev/null +++ b/doc/html/classes.html @@ -0,0 +1,17 @@ + + +uIP 0.9: Alphabetical index + + + + +

    uIP 0.9 Data Structure Index

    +
      F  
    +
      T  
    +
      U  
    +
    uip_eth_addr   uip_stats   
    fs_file   telnetd_state   uip_conn   uip_eth_hdr   uip_udp_conn   

    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/doxygen.css b/doc/html/doxygen.css new file mode 100644 index 0000000..0564e82 --- /dev/null +++ b/doc/html/doxygen.css @@ -0,0 +1,160 @@ +H1 { + text-align: center; + font-family: Arial, Helvetica, sans-serif; +} +H2 { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +CAPTION { font-weight: bold } +DIV.qindex { width: 100%; + background-color: #eeeeff; + border: 4px solid #eeeeff; + text-align: center; + margin-bottom: 2px +} +A.qindex { text-decoration: none; font-weight: bold; } +A.qindex:hover { text-decoration: none; background-color: #ddddff } +A.qindexHL { text-decoration: none; font-weight: bold; + background-color: #6666cc; + color: #ffffff + } +A.qindexHL:hover { text-decoration: none; background-color: #6666cc } +A.qindexRef { text-decoration: none; font-weight: bold; } +A.qindexRef:hover { text-decoration: none; background-color: #ddddff } +A.qindexRefHL { text-decoration: none; font-weight: bold; + background-color: #6666cc; + color: #ffffff + } +A.qindexRefHL:hover { text-decoration: none; background-color: #6666cc } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal; color: #4444ee } +A.codeRef { font-weight: normal; color: #4444ee } +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +DIV.fragment { + width: 98%; + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + padding-left: 4px; + margin: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #f2f2ff; font-weight: bold; } +TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; } +TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } +DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #f2f2ff; +} +.mdRow { + padding: 8px 20px; +} +.mdescLeft { + font-size: smaller; + font-family: Arial, Helvetica, sans-serif; + background-color: #FAFAFA; + padding-left: 8px; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + font-size: smaller; + font-family: Arial, Helvetica, sans-serif; + font-style: italic; + background-color: #FAFAFA; + padding-left: 4px; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; + padding-bottom: 0px; + padding-right: 8px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-family: Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; +} +.memItemRight { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-family: Geneva, Arial, Helvetica, sans-serif; + font-size: 13px; +} diff --git a/doc/html/doxygen.png b/doc/html/doxygen.png new file mode 100644 index 0000000..96ae72c Binary files /dev/null and b/doc/html/doxygen.png differ diff --git a/doc/html/files.html b/doc/html/files.html new file mode 100644 index 0000000..354ae61 --- /dev/null +++ b/doc/html/files.html @@ -0,0 +1,40 @@ + + +uIP 0.9: File Index + + + + +

    uIP 0.9 File List

    Here is a list of all documented files with brief descriptions: + + + + + + + + + + + + + + + + + + + + + + + + + +
    apps/httpd/cgi.cHTTP server script language C functions file
    apps/httpd/cgi.hHTTP script language header file
    apps/httpd/fs.cHTTP server read-only file system code
    apps/httpd/fs.hHTTP server read-only file system header file
    apps/httpd/httpd.cHTTP server
    apps/httpd/httpd.hHTTP server header file
    apps/resolv/resolv.cDNS host name to IP address resolver
    apps/resolv/resolv.hDNS resolver code header file
    apps/smtp/smtp.cSMTP example implementation
    apps/smtp/smtp.hSMTP header file
    apps/telnetd/memb.cMemory block allocation routines
    apps/telnetd/memb.hMemory block allocation routines
    apps/telnetd/telnetd-shell.cAn example telnet server shell
    apps/telnetd/telnetd.cImplementation of the Telnet server
    apps/telnetd/telnetd.hHeader file for the telnet server
    apps/webclient/webclient.cImplementation of the HTTP client
    apps/webclient/webclient.hHeader file for the HTTP client
    uip/slipdev.cSLIP protocol implementation
    uip/slipdev.hSLIP header file
    uip/uip.cThe uIP TCP/IP stack code
    uip/uip.hHeader file for the uIP TCP/IP stack
    uip/uip_arch.hDeclarations of architecture specific functions
    uip/uip_arp.cImplementation of the ARP Address Resolution Protocol
    uip/uip_arp.hMacros and definitions for the ARP module
    unix/uipopt.hConfiguration options for uIP
    +
    Generated on Tue Oct 7 15:51:00 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/ftv2blank.png b/doc/html/ftv2blank.png new file mode 100644 index 0000000..493c3c0 Binary files /dev/null and b/doc/html/ftv2blank.png differ diff --git a/doc/html/ftv2doc.png b/doc/html/ftv2doc.png new file mode 100644 index 0000000..f72999f Binary files /dev/null and b/doc/html/ftv2doc.png differ diff --git a/doc/html/ftv2folderclosed.png b/doc/html/ftv2folderclosed.png new file mode 100644 index 0000000..d6d0634 Binary files /dev/null and b/doc/html/ftv2folderclosed.png differ diff --git a/doc/html/ftv2folderopen.png b/doc/html/ftv2folderopen.png new file mode 100644 index 0000000..bbe2c91 Binary files /dev/null and b/doc/html/ftv2folderopen.png differ diff --git a/doc/html/ftv2lastnode.png b/doc/html/ftv2lastnode.png new file mode 100644 index 0000000..e7b9ba9 Binary files /dev/null and b/doc/html/ftv2lastnode.png differ diff --git a/doc/html/ftv2link.png b/doc/html/ftv2link.png new file mode 100644 index 0000000..14f3fed Binary files /dev/null and b/doc/html/ftv2link.png differ diff --git a/doc/html/ftv2mlastnode.png b/doc/html/ftv2mlastnode.png new file mode 100644 index 0000000..09ceb6a Binary files /dev/null and b/doc/html/ftv2mlastnode.png differ diff --git a/doc/html/ftv2mnode.png b/doc/html/ftv2mnode.png new file mode 100644 index 0000000..3254c05 Binary files /dev/null and b/doc/html/ftv2mnode.png differ diff --git a/doc/html/ftv2node.png b/doc/html/ftv2node.png new file mode 100644 index 0000000..c9f06a5 Binary files /dev/null and b/doc/html/ftv2node.png differ diff --git a/doc/html/ftv2plastnode.png b/doc/html/ftv2plastnode.png new file mode 100644 index 0000000..0b07e00 Binary files /dev/null and b/doc/html/ftv2plastnode.png differ diff --git a/doc/html/ftv2pnode.png b/doc/html/ftv2pnode.png new file mode 100644 index 0000000..2001b79 Binary files /dev/null and b/doc/html/ftv2pnode.png differ diff --git a/doc/html/ftv2vertline.png b/doc/html/ftv2vertline.png new file mode 100644 index 0000000..b330f3a Binary files /dev/null and b/doc/html/ftv2vertline.png differ diff --git a/doc/html/functions.html b/doc/html/functions.html new file mode 100644 index 0000000..4e07f49 --- /dev/null +++ b/doc/html/functions.html @@ -0,0 +1,95 @@ + + +uIP 0.9: Compound Member Index + + + + + +
    a | c | d | f | h | i | l | m | n | p | r | s | t | v
    + +

    + +

    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:

    - a - +

    +

    - c - +

    +

    - d - +

    +

    - f - +

    +

    - h - +

    +

    - i - +

    +

    - l - +

    +

    - m - +

    +

    - n - +

    +

    - p - +

    +

    - r - +

    +

    - s - +

    +

    - t - +

    +

    - v - +

    +
    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html new file mode 100644 index 0000000..3d2eaa0 --- /dev/null +++ b/doc/html/functions_vars.html @@ -0,0 +1,95 @@ + + +uIP 0.9: Compound Member Index + + + + + +
    a | c | d | f | h | i | l | m | n | p | r | s | t | v
    + +

    + +

    +

    - a - +

    +

    - c - +

    +

    - d - +

    +

    - f - +

    +

    - h - +

    +

    - i - +

    +

    - l - +

    +

    - m - +

    +

    - n - +

    +

    - p - +

    +

    - r - +

    +

    - s - +

    +

    - t - +

    +

    - v - +

    +
    Generated on Tue Oct 7 15:51:41 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/globals.html b/doc/html/globals.html new file mode 100644 index 0000000..51aba16 --- /dev/null +++ b/doc/html/globals.html @@ -0,0 +1,197 @@ + + +uIP 0.9: File Member Index + + + + + +
    b | c | f | h | m | r | s | t | u | w
    + +

    + +

    +Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

    - b - +

    +

    - c - +

    +

    - f - +

    +

    - h - +

    +

    - m - +

    +

    - r - +

    +

    - s - +

    +

    - t - +

    +

    - u - +

    +

    - w - +

    +
    Generated on Tue Oct 7 15:51:52 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/globals_defs.html b/doc/html/globals_defs.html new file mode 100644 index 0000000..8674983 --- /dev/null +++ b/doc/html/globals_defs.html @@ -0,0 +1,122 @@ + + +uIP 0.9: File Member Index + + + + + +
    b | h | m | s | t | u
    + +

    + +

    +

    - b - +

    +

    - h - +

    +

    - m - +

    +

    - s - +

    +

    - t - +

    +

    - u - +

    +
    Generated on Tue Oct 7 15:51:52 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/globals_func.html b/doc/html/globals_func.html new file mode 100644 index 0000000..729e8ce --- /dev/null +++ b/doc/html/globals_func.html @@ -0,0 +1,98 @@ + + +uIP 0.9: File Member Index + + + + + +
    f | h | m | r | s | t | u | w
    + +

    + +

    +

    - f - +

    +

    - h - +

    +

    - m - +

    +

    - r - +

    +

    - s - +

    +

    - t - +

    +

    - u - +

    +

    - w - +

    +
    Generated on Tue Oct 7 15:51:52 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/globals_type.html b/doc/html/globals_type.html new file mode 100644 index 0000000..f14f00c --- /dev/null +++ b/doc/html/globals_type.html @@ -0,0 +1,21 @@ + + +uIP 0.9: File Member Index + + + + + + +

    +

    +
    Generated on Tue Oct 7 15:51:52 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/globals_vars.html b/doc/html/globals_vars.html new file mode 100644 index 0000000..0e55ac9 --- /dev/null +++ b/doc/html/globals_vars.html @@ -0,0 +1,23 @@ + + +uIP 0.9: File Member Index + + + + + + +

    +

    +
    Generated on Tue Oct 7 15:51:52 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/graph_legend.dot b/doc/html/graph_legend.dot new file mode 100644 index 0000000..5420927 --- /dev/null +++ b/doc/html/graph_legend.dot @@ -0,0 +1,22 @@ +digraph G +{ + edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; + node [fontname="Helvetica",fontsize=10,shape=record]; + Node9 [shape="box",label="Inherited",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="black",style="filled" fontcolor="white"]; + Node10 -> Node9 [dir=back,color="midnightblue",fontsize=10,style="solid",fontname="Helvetica"]; + Node10 [shape="box",label="PublicBase",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classPublicBase.html"]; + Node11 -> Node10 [dir=back,color="midnightblue",fontsize=10,style="solid",fontname="Helvetica"]; + Node11 [shape="box",label="Truncated",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="red",URL="$classTruncated.html"]; + Node13 -> Node9 [dir=back,color="darkgreen",fontsize=10,style="solid",fontname="Helvetica"]; + Node13 [shape="box",label="ProtectedBase",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classProtectedBase.html"]; + Node14 -> Node9 [dir=back,color="firebrick4",fontsize=10,style="solid",fontname="Helvetica"]; + Node14 [shape="box",label="PrivateBase",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classPrivateBase.html"]; + Node15 -> Node9 [dir=back,color="midnightblue",fontsize=10,style="solid",fontname="Helvetica"]; + Node15 [shape="box",label="Undocumented",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="grey75"]; + Node16 -> Node9 [dir=back,color="midnightblue",fontsize=10,style="solid",fontname="Helvetica"]; + Node16 [shape="box",label="Templ< int >",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classTempl.html"]; + Node17 -> Node16 [dir=back,color="orange",fontsize=10,style="dashed",label="< int >",fontname="Helvetica"]; + Node17 [shape="box",label="Templ< T >",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classTempl.html"]; + Node18 -> Node9 [dir=back,color="darkorchid3",fontsize=10,style="dashed",label="m_usedClass",fontname="Helvetica"]; + Node18 [shape="box",label="Used",fontsize=10,height=0.2,width=0.4,fontname="Helvetica",color="black",URL="$classUsed.html"]; +} diff --git a/doc/html/graph_legend.html b/doc/html/graph_legend.html new file mode 100644 index 0000000..eaf61c9 --- /dev/null +++ b/doc/html/graph_legend.html @@ -0,0 +1,75 @@ + + +uIP 0.9: Graph Legend + + + + +

    Graph Legend

    This page explains how to interpret the graphs that are generated by doxygen.

    +Consider the following example:

    /*! Invisible class because of truncation */
    +class Invisible { };
    +
    +/*! Truncated class, inheritance relation is hidden */
    +class Truncated : public Invisible { };
    +
    +/* Class not documented with doxygen comments */
    +class Undocumented { };
    +
    +/*! Class that is inherited using public inheritance */
    +class PublicBase : public Truncated { };
    +
    +/*! A template class */
    +template<class T> class Templ { };
    +
    +/*! Class that is inherited using protected inheritance */
    +class ProtectedBase { };
    +
    +/*! Class that is inherited using private inheritance */
    +class PrivateBase { };
    +
    +/*! Class that is used by the Inherited class */
    +class Used { };
    +
    +/*! Super class that inherits a number of other classes */
    +class Inherited : public PublicBase,
    +                  protected ProtectedBase,
    +                  private PrivateBase,
    +                  public Undocumented
    +                  public Templ<int>
    +{
    +  private:
    +    Used *m_usedClass;
    +};
    +
    If the MAX_DOT_GRAPH_HEIGHT tag in the configuration file is set to 240 this will result in the following graph:

    +

    +graph_legend.png +
    +

    +The boxes in the above graph have the following meaning:

      +
    • +A filled black box represents the struct or class for which the graph is generated.
    • +
    • +A box with a black border denotes a documented struct or class.
    • +
    • +A box with a grey border denotes an undocumented struct or class.
    • +
    • +A box with a red border denotes a documented struct or class forwhich not all inheritance/containment relations are shown. A graph is truncated if it does not fit within the specified boundaries.
    • +
    +The arrows have the following meaning:
      +
    • +A dark blue arrow is used to visualize a public inheritance relation between two classes.
    • +
    • +A dark green arrow is used for protected inheritance.
    • +
    • +A dark red arrow is used for private inheritance.
    • +
    • +A purple dashed arrow is used if a class is contained or used by another class. The arrow is labeled with the variable(s) through which the pointed class or struct is accessible.
    • +
    • +A yellow dashed arrow denotes a relation between a template instance and the template class it was instantiated from. The arrow is labeled with the template parameters of the instance.
    • +
    +
    Generated on Tue Oct 7 15:51:52 2003 for uIP 0.9 by + +doxygen +1.3.3
    + + diff --git a/doc/html/graph_legend.png b/doc/html/graph_legend.png new file mode 100644 index 0000000..8a116c2 Binary files /dev/null and b/doc/html/graph_legend.png differ diff --git a/doc/html/index.hhc b/doc/html/index.hhc new file mode 100644 index 0000000..3d7036c --- /dev/null +++ b/doc/html/index.hhc @@ -0,0 +1,126 @@ + + + + + +
      +
    • +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
    • +
        +
      • +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        +
      • +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        +
      • +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        • +
            +
          +
        +
      +
    • +
    diff --git a/doc/html/index.hhk b/doc/html/index.hhk new file mode 100644 index 0000000..664e519 --- /dev/null +++ b/doc/html/index.hhk @@ -0,0 +1,725 @@ + + + + + +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      +
    • +
        +
      • +
      diff --git a/doc/html/index.hhp b/doc/html/index.hhp new file mode 100644 index 0000000..50ec072 --- /dev/null +++ b/doc/html/index.hhp @@ -0,0 +1,86 @@ +[OPTIONS] +Compatibility=1.1 +Full-text search=Yes +Contents file=index.hhc +Default Window=main +Default topic=main.html +Index file=index.hhk +Language=0x409 English (United States) +Binary TOC=YES +Create CHI file=YES +Title=uIP 0.9 + +[WINDOWS] +main="uIP 0.9","index.hhc","index.hhk","main.html","main.html",,,,,0x23520,,0x387e,,,,,,,,0 + +[FILES] +main.html +files.html +a00049.html +a00050.html +a00051.html +a00052.html +a00053.html +a00054.html +a00055.html +a00056.html +a00057.html +a00058.html +a00059.html +a00060.html +a00061.html +a00062.html +a00063.html +a00064.html +a00065.html +a00067.html +a00068.html +a00069.html +a00070.html +a00071.html +a00072.html +a00073.html +a00074.html +annotated.html +classes.html +functions.html +functions_vars.html +a00030.html +a00036.html +a00037.html +a00038.html +a00039.html +a00041.html +a00046.html +a00075.html +a00076.html +a00077.html +a00078.html +a00079.html +a00080.html +a00081.html +a00082.html +a00083.html +a00084.html +a00085.html +a00086.html +a00087.html +a00088.html +a00089.html +a00090.html +a00091.html +a00092.html +a00093.html +a00094.html +a00095.html +a00096.html +a00097.html +a00098.html +a00099.html +modules.html +globals.html +globals_func.html +globals_vars.html +globals_type.html +globals_defs.html +graph_legend.html diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..c1594de --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,8 @@ + + +uIP 0.9 + + + + + diff --git a/doc/html/main.html b/doc/html/main.html new file mode 100644 index 0000000..605809b --- /dev/null +++ b/doc/html/main.html @@ -0,0 +1,351 @@ + + +uIP 0.9: The uIP TCP/IP stack + + + + +

      The uIP TCP/IP stack

      +

      +

      Author:
      Adam Dunkels <adam@dunkels.com>
      +The uIP TCP/IP stack is intended to make it possible to communicate using the TCP/IP protocol suite even on small 8-bit micro-controllers. Despite being small and simple, uIP do not require their peers to have complex, full-size stacks, but can communicate with peers running a similarly light-weight stack. The code size is on the order of a few kilobytes and RAM usage can be configured to be as low as a few hundred bytes.

      +uIP introduction

      +With the success of the Internet, the TCP/IP protocol suite has become a global standard for communication. TCP/IP is the underlying protocol used for web page transfers, e-mail transmissions, file transfers, and peer-to-peer networking over the Internet. For embedded systems, being able to run native TCP/IP makes it possible to connect the system directly to an intranet or even the global Internet. Embedded devices with full TCP/IP support will be first-class network citizens, thus being able to fully communicate with other hosts in the network.

      +Traditional TCP/IP implementations have required far too much resources both in terms of code size and memory usage to be useful in small 8 or 16-bit systems. Code size of a few hundred kilobytes and RAM requirements of several hundreds of kilobytes have made it impossible to fit the full TCP/IP stack into systems with a few tens of kilobytes of RAM and room for less than 100 kilobytes of code.

      +The uIP implementation is designed to have only the absolute minimal set of features needed for a full TCP/IP stack. It can only handle a single network interface and contains only a rudimentary UDP implementation, but focuses on the IP, ICMP and TCP protocols. uIP is written in the C programming language.

      +Many other TCP/IP implementations for small systems assume that the embedded device always will communicate with a full-scale TCP/IP implementation running on a workstation-class machine. Under this assumption, it is possible to remove certain TCP/IP mechanisms that are very rarely used in such situations. Many of those mechanisms are essential, however, if the embedded device is to communicate with another equally limited device, e.g., when running distributed peer-to-peer services and protocols. uIP is designed to be RFC compliant in order to let the embedded devices to act as first-class network citizens. The uIP TCP/IP implementation that is not tailored for any specific application.

      +TCP/IP communication

      +The full TCP/IP suite consists of numerous protocols, ranging from low level protocols such as ARP which translates IP addresses to MAC addresses, to application level protocols such as SMTP that is used to transfer e-mail. The uIP is mostly concerned with the TCP and IP protocols and upper layer protocols will be referred to as "the application". Lower layer protocols are often implemented in hardware or firmware and will be referred to as "the network device" that are controlled by the network device driver.

      +TCP provides a reliable byte stream to the upper layer protocols. It breaks the byte stream into appropriately sized segments and each segment is sent in its own IP packet. The IP packets are sent out on the network by the network device driver. If the destination is not on the physically connected network, the IP packet is forwarded onto another network by a router that is situated between the two networks. If the maximum packet size of the other network is smaller than the size of the IP packet, the packet is fragmented into smaller packets by the router. If possible, the size of the TCP segments are chosen so that fragmentation is minimized. The final recipient of the packet will have to reassemble any fragmented IP packets before they can be passed to higher layers.

      +The formal requirements for the protocols in the TCP/IP stack is specified in a number of RFC documents published by the Internet Engineering Task Force, IETF. Each of the protocols in the stack is defined in one more RFC documents and RFC1122 collects all requirements and updates the previous RFCs.

      +The RFC1122 requirements can be divided into two categories; those that deal with the host to host communication and those that deal with communication between the application and the networking stack. An example of the first kind is "A TCP MUST be able to receive a TCP option in any segment" and an example of the second kind is "There MUST be a mechanism for reporting soft TCP error conditions to the application." A TCP/IP implementation that violates requirements of the first kind may not be able to communicate with other TCP/IP implementations and may even lead to network failures. Violation of the second kind of requirements will only affect the communication within the system and will not affect host-to-host communication.

      +In uIP, all RFC requirements that affect host-to-host communication are implemented. However, in order to reduce code size, we have removed certain mechanisms in the interface between the application and the stack, such as the soft error reporting mechanism and dynamically configurable type-of-service bits for TCP connections. Since there are only very few applications that make use of those features they can be removed without loss of generality.

      +Memory management

      +In the architectures for which uIP is intended, RAM is the most scarce resource. With only a few kilobytes of RAM available for the TCP/IP stack to use, mechanisms used in traditional TCP/IP cannot be directly applied.

      +The uIP stack does not use explicit dynamic memory allocation. Instead, it uses a single global buffer for holding packets and has a fixed table for holding connection state. The global packet buffer is large enough to contain one packet of maximum size. When a packet arrives from the network, the device driver places it in the global buffer and calls the TCP/IP stack. If the packet contains data, the TCP/IP stack will notify the corresponding application. Because the data in the buffer will be overwritten by the next incoming packet, the application will either have to act immediately on the data or copy the data into a secondary buffer for later processing. The packet buffer will not be overwritten by new packets before the application has processed the data. Packets that arrive when the application is processing the data must be queued, either by the network device or by the device driver. Most single-chip Ethernet controllers have on-chip buffers that are large enough to contain at least 4 maximum sized Ethernet frames. Devices that are handled by the processor, such as RS-232 ports, can copy incoming bytes to a separate buffer during application processing. If the buffers are full, the incoming packet is dropped. This will cause performance degradation, but only when multiple connections are running in parallel. This is because uIP advertises a very small receiver window, which means that only a single TCP segment will be in the network per connection.

      +In uIP, the same global packet buffer that is used for incoming packets is also used for the TCP/IP headers of outgoing data. If the application sends dynamic data, it may use the parts of the global packet buffer that are not used for headers as a temporary storage buffer. To send the data, the application passes a pointer to the data as well as the length of the data to the stack. The TCP/IP headers are written into the global buffer and once the headers have been produced, the device driver sends the headers and the application data out on the network. The data is not queued for retransmissions. Instead, the application will have to reproduce the data if a retransmission is necessary.

      +The total amount of memory usage for uIP depends heavily on the applications of the particular device in which the implementations are to be run. The memory configuration determines both the amount of traffic the system should be able to handle and the maximum amount of simultaneous connections. A device that will be sending large e-mails while at the same time running a web server with highly dynamic web pages and multiple simultaneous clients, will require more RAM than a simple Telnet server. It is possible to run the uIP implementation with as little as 200 bytes of RAM, but such a configuration will provide extremely low throughput and will only allow a small number of simultaneous connections.

      +Application program interface (API)

      +The Application Program Interface (API) defines the way the application program interacts with the TCP/IP stack. The most commonly used API for TCP/IP is the BSD socket API which is used in most Unix systems and has heavily influenced the Microsoft Windows WinSock API. Because the socket API uses stop-and-wait semantics, it requires support from an underlying multitasking operating system. Since the overhead of task management, context switching and allocation of stack space for the tasks might be too high in the intended uIP target architectures, the BSD socket interface is not suitable for our purposes.

      +Instead, uIP uses an event driven interface where the application is invoked in response to certain events. An application running on top of uIP is implemented as a C function that is called by uIP in response to certain events. uIP calls the application when data is received, when data has been successfully delivered to the other end of the connection, when a new connection has been set up, or when data has to be retransmitted. The application is also periodically polled for new data. The application program provides only one callback function; it is up to the application to deal with mapping different network services to different ports and connections. Because the application is able to act on incoming data and connection requests as soon as the TCP/IP stack receives the packet, low response times can be achieved even in low-end systems.

      +uIP is different from other TCP/IP stacks in that it requires help from the application when doing retransmissions. Other TCP/IP stacks buffer the transmitted data in memory until the data is known to be successfully delivered to the remote end of the connection. If the data needs to be retransmitted, the stack takes care of the retransmission without notifying the application. With this approach, the data has to be buffered in memory while waiting for an acknowledgment even if the application might be able to quickly regenerate the data if a retransmission has to be made.

      +In order to reduce memory usage, uIP utilizes the fact that the application may be able to regenerate sent data and lets the application take part in retransmissions. uIP does not keep track of packet contents after they have been sent by the device driver, and uIP requires that the application takes an active part in performing the retransmission. When uIP decides that a segment should be retransmitted, it calls the application with a flag set indicating that a retransmission is required. The application checks the retransmission flag and produces the same data that was previously sent. From the application's standpoint, performing a retransmission is not different from how the data originally was sent. Therefore the application can be written in such a way that the same code is used both for sending data and retransmitting data. Also, it is important to note that even though the actual retransmission operation is carried out by the application, it is the responsibility of the stack to know when the retransmission should be made. Thus the complexity of the application does not necessarily increase because it takes an active part in doing retransmissions.

      +Application events

      +The application must be implemented as a C function, UIP_APPCALL(), that uIP calls whenever an event occurs. Each event has a corresponding test function that is used to distinguish between different events. The functions are implemented as C macros that will evaluate to either zero or non-zero. Note that certain events can happen in conjunction with each other (i.e., new data can arrive at the same time as data is acknowledged).

      +The connection pointer

      +When the application is called by uIP, the global variable uip_conn is set to point to the uip_conn structure for the connection that currently is handled, and is called the "current connection". The fields in the uip_conn structure for the current connection can be used, e.g., to distinguish between different services, or to check to which IP address the connection is connected. One typical use would be to inspect the uip_conn->lport (the local TCP port number) to decide which service the connection should provide. For instance, an application might decide to act as an HTTP server if the value of uip_conn->lport is equal to 80 and act as a TELNET server if the value is 23.

      +Receiving data

      +If the uIP test function uip_newdata() is non-zero, the remote host of the connection has sent new data. The uip_appdata pointer point to the actual data. The size of the data is obtained through the uIP function uip_datalen(). The data is not buffered by uIP, but will be overwritten after the application function returns, and the application will therefor have to either act directly on the incoming data, or by itself copy the incoming data into a buffer for later processing.

      +Sending data

      +When sending data, uIP adjusts the length of the data sent by the application according to the available buffer space and the current TCP window advertised by the receiver. The amount of buffer space is dictated by the memory configuration. It is therefore possible that all data sent from the application does not arrive at the receiver, and the application may use the uip_mss() function to see how much data that actually will be sent by the stack.

      +The application sends data by using the uIP function uip_send(). The uip_send() function takes two arguments; a pointer to the data to be sent and the length of the data. If the application needs RAM space for producing the actual data that should be sent, the packet buffer (pointed to by the uip_appdata pointer) can be used for this purpose.

      +The application can send only one chunk of data at a time on a connection and it is not possible to call uip_send() more than once per application invocation; only the data from the last call will be sent.

      +Retransmitting data

      +Retransmissions are driven by the periodic TCP timer. Every time the periodic timer is invoked, the retransmission timer for each connection is decremented. If the timer reaches zero, a retransmission should be made. As uIP does not keep track of packet contents after they have been sent by the device driver, uIP requires that the application takes an active part in performing the retransmission. When uIP decides that a segment should be retransmitted, the application function is called with the uip_rexmit() flag set, indicating that a retransmission is required.

      +The application must check the uip_rexmit() flag and produce the same data that was previously sent. From the application's standpoint, performing a retransmission is not different from how the data originally was sent. Therefor, the application can be written in such a way that the same code is used both for sending data and retransmitting data. Also, it is important to note that even though the actual retransmission operation is carried out by the application, it is the responsibility of the stack to know when the retransmission should be made. Thus the complexity of the application does not necessarily increase because it takes an active part in doing retransmissions.

      +Closing connections

      +The application closes the current connection by calling the uip_close() during an application call. This will cause the connection to be cleanly closed. In order to indicate a fatal error, the application might want to abort the connection and does so by calling the uip_abort() function.

      +If the connection has been closed by the remote end, the test function uip_closed() is true. The application may then do any necessary cleanups.

      +Reporting errors

      +There are two fatal errors that can happen to a connection, either that the connection was aborted by the remote host, or that the connection retransmitted the last data too many times and has been aborted. uIP reports this by calling the application function. The application can use the two test functions uip_aborted() and uip_timedout() to test for those error conditions.

      +Polling

      +When a connection is idle, uIP polls the application every time the periodic timer fires. The application uses the test function uip_poll() to check if it is being polled by uIP.

      +The polling event has two purposes. The first is to let the application periodically know that a connection is idle, which allows the application to close connections that have been idle for too long. The other purpose is to let the application send new data that has been produced. The application can only send data when invoked by uIP, and therefore the poll event is the only way to send data on an otherwise idle connection.

      +Listening ports

      +uIP maintains a list of listening TCP ports. A new port is opened for listening with the uip_listen() function. When a connection request arrives on a listening port, uIP creates a new connection and calls the application function. The test function uip_connected() is true if the application was invoked because a new connection was created.

      +The application can check the lport field in the uip_conn structure to check to which port the new connection was connected.

      +Opening connections

      +New connections can be opened from within uIP by the function uip_connect(). This function allocates a new connection and sets a flag in the connection state which will open a TCP connection to the specified IP address and port the next time the connection is polled by uIP. The uip_connect() function returns a pointer to the uip_conn structure for the new connection. If there are no free connection slots, the function returns NULL.

      +The function uip_ipaddr() may be used to pack an IP address into the two element 16-bit array used by uIP to represent IP addresses.

      +Two examples of usage are shown below. The first example shows how to open a connection to TCP port 8080 of the remote end of the current connection. If there are not enough TCP connection slots to allow a new connection to be opened, the uip_connect() function returns NULL and the current connection is aborted by uip_abort().

      +

      void connect_example1_app(void) {
      +   if(uip_connect(uip_conn->ripaddr, HTONS(8080)) == NULL) {
      +      uip_abort();
      +   }
      +}   
      +

      +The second example shows how to open a new connection to a specific IP address. No error checks are made in this example.

      +

      void connect_example2(void) {
      +   u16_t ipaddr[2];
      +
      +   uip_ipaddr(ipaddr, 192,168,0,1);
      +   uip_connect(ipaddr, HTONS(8080));
      +}
      +

      +uIP device drivers

      +From the network device driver's standpoint, uIP consists of two C functions: uip_input() and uip_periodic(). The uip_input() function should be called by the device driver when an IP packet has been received and put into the uip_buf packet buffer. The uip_input() function will process the packet, and when it returns an outbound packet may have been placed in the same uip_buf packet buffer (indicated by the uip_len variable being non-zero). The device driver should then send out this packet onto the network.

      +The uip_periodic() function should be invoked periodically once per connection by the device driver, typically one per second. This function is used by uIP to drive protocol timers and retransmissions, and when it returns it may have placed an outbound packet in the uip_buf buffer.

      +Architecture specific functions

      +uIP requires a few functions to be implemented specifically for the architecture on which uIP is intended to run. These functions should be hand-tuned for the particular architecture, but generic C implementations are given as part of the uIP distribution.

      +Checksum calculation

      +The TCP and IP protocols implement a checksum that covers the data and header portions of the TCP and IP packets. Since the calculation of this checksum is made over all bytes in every packet being sent and received it is important that the function that calculates the checksum is efficient. Most often, this means that the checksum calculation must be fine-tuned for the particular architecture on which the uIP stack runs.

      +Because of this, uIP does not implement a generic checksum function, but leaves this to the architecture specific files which must implement the two functions uip_ipchksum() and uip_tcpchksum(). The checksum calculations in those functions can be written in highly optimized assembler rather than generic C code.

      +An example C implementation of the checksum function is provided in the uIP distribution.

      +32-bit arithmetic

      +The TCP protocol uses 32-bit sequence numbers, and a TCP implementation will have to do a number of 32-bit additions as part of the normal protocol processing. Since 32-bit arithmetic is not natively available on many of the platforms for which uIP is intended, uIP leaves the 32-bit additions to be implemented by the architecture specific module and does not make use of any 32-bit arithmetic in the main code base.

      +The architecture specific code must implement a function uip_add32() which does a 32-bit addition and stores the result in a global variable uip_acc32.

      +Examples

      +This section presents a number of very simple uIP applications. The uIP code distribution contains several more complex applications.

      +A very simple application

      +This first example shows a very simple application. The application listens for incoming connections on port 1234. When a connection has been established, the application replies to all data sent to it by saying "ok"

      +The implementation of this application is shown below. The application is initialized with the function called example1_init() and the uIP callback function is called example1_app(). For this application, the configuration variable UIP_APPCALL should be defined to be example1_app().

      +

      void example1_init(void) {
      +   uip_listen(HTONS(1234));
      +}
      +
      +void example1_app(void) {
      +   if(uip_newdata() || uip_rexmit()) {
      +      uip_send("ok\n", 3);
      +   }
      +}
      +

      +The initialization function calls the uIP function uip_listen() to register a listening port. The actual application function example1_app() uses the test functions uip_newdata() and uip_rexmit() to determine why it was called. If the application was called because the remote end has sent it data, it responds with an "ok". If the application function was called because data was lost in the network and has to be retransmitted, it also sends an "ok". Note that this example actually shows a complete uIP application. It is not required for an application to deal with all types of events such as uip_connected() or uip_timedout().

      +A more advanced application

      +This second example is slightly more advanced than the previous one, and shows how the application state field in the uip_conn structure is used.

      +This application is similar to the first application in that it listens to a port for incoming connections and responds to data sent to it with a single "ok". The big difference is that this application prints out a welcoming "Welcome!" message when the connection has been established.

      +This seemingly small change of operation makes a big difference in how the application is implemented. The reason for the increase in complexity is that if data should be lost in the network, the application must know what data to retransmit. If the "Welcome!" message was lost, the application must retransmit the welcome and if one of the "ok" messages is lost, the application must send a new "ok".

      +The application knows that as long as the "Welcome!" message has not been acknowledged by the remote host, it might have been dropped in the network. But once the remote host has sent an acknowledgment back, the application can be sure that the welcome has been received and knows that any lost data must be an "ok" message. Thus the application can be in either of two states: either in the WELCOME-SENT state where the "Welcome!" has been sent but not acknowledged, or in the WELCOME-ACKED state where the "Welcome!" has been acknowledged.

      +When a remote host connects to the application, the application sends the "Welcome!" message and sets it's state to WELCOME-SENT. When the welcome message is acknowledged, the application moves to the WELCOME-ACKED state. If the application receives any new data from the remote host, it responds by sending an "ok" back.

      +If the application is requested to retransmit the last message, it looks at in which state the application is. If the application is in the WELCOME-SENT state, it sends a "Welcome!" message since it knows that the previous welcome message hasn't been acknowledged. If the application is in the WELCOME-ACKED state, it knows that the last message was an "ok" message and sends such a message.

      +The implementation of this application is seen below. This configuration settings for the application is follows after its implementation.

      +

      struct example2_state {
      +   enum {WELCOME_SENT, WELCOME_ACKED} state;
      +};
      +
      +void example2_init(void) {
      +   uip_listen(HTONS(2345));
      +}
      +
      +void example2_app(void) {
      +   struct example2_state *s;
      +
      +   s = (struct example2_state *)uip_conn->appstate;
      +   
      +   if(uip_connected()) {
      +      s->state = WELCOME_SENT;
      +      uip_send("Welcome!\n", 9);
      +      return;
      +   } 
      +
      +   if(uip_acked() && s->state == WELCOME_SENT) {
      +      s->state = WELCOME_ACKED;
      +   }
      +
      +   if(uip_newdata()) {
      +      uip_send("ok\n", 3);
      +   }
      +
      +   if(uip_rexmit()) {
      +      switch(s->state) {
      +      case WELCOME_SENT:
      +         uip_send("Welcome!\n", 9);
      +         break;
      +      case WELCOME_ACKED:
      +         uip_send("ok\n", 3);
      +         break;
      +      }
      +   }
      +}
      +

      +The configuration for the application:

      +

      #define UIP_APPCALL       example2_app
      +#define UIP_APPSTATE_SIZE sizeof(struct example2_state)
      +

      +Differentiating between applications

      +If the system should run multiple applications, one technique to differentiate between them is to use the TCP port number of either the remote end or the local end of the connection. The example below shows how the two examples above can be combined into one application.

      +

      void example3_init(void) {
      +   example1_init();
      +   example2_init();   
      +}
      +
      +void example3_app(void) {
      +   switch(uip_conn->lport) {
      +   case HTONS(1234):
      +      example1_app();
      +      break;
      +   case HTONS(2345):
      +      example2_app();
      +      break;
      +   }
      +}
      +

      +Utilizing TCP flow control

      +This example shows a simple application that connects to a host, sends an HTTP request for a file and downloads it to a slow device such a disk drive. This shows how to use the flow control functions of uIP.

      +

      void example4_init(void) {
      +   u16_t ipaddr[2];
      +   uip_ipaddr(ipaddr, 192,168,0,1);
      +   uip_connect(ipaddr, HTONS(80));
      +}
      +
      +void example4_app(void) {
      +   if(uip_connected() || uip_rexmit()) {
      +      uip_send("GET /file HTTP/1.0\r\nServer:192.186.0.1\r\n\r\n",
      +               48);
      +      return;
      +   }
      +
      +   if(uip_newdata()) {
      +      device_enqueue(uip_appdata, uip_datalen());
      +      if(device_queue_full()) {
      +         uip_stop();
      +      }
      +   }
      +
      +   if(uip_poll() && uip_stopped()) {
      +      if(!device_queue_full()) {
      +         uip_restart();
      +      }
      +   }
      +}
      +

      +When the connection has been established, an HTTP request is sent to the server. Since this is the only data that is sent, the application knows that if it needs to retransmit any data, it is that request that should be retransmitted. It is therefore possible to combine these two events as is done in the example.

      +When the application receives new data from the remote host, it sends this data to the device by using the function device_enqueue(). It is important to note that this example assumes that this function copies the data into its own buffers. The data in the uip_appdata buffer will be overwritten by the next incoming packet.

      +If the device's queue is full, the application stops the data from the remote host by calling the uIP function uip_stop(). The application can then be sure that it will not receive any new data until uip_restart() is called. The application polling event is used to check if the device's queue is no longer full and if so, the data flow is restarted with uip_restart().

      +A simple web server

      +This example shows a very simple file server application that listens to two ports and uses the port number to determine which file to send. If the files are properly formatted, this simple application can be used as a web server with static pages. The implementation follows.

      +

      struct example5_state {
      +   char *dataptr;
      +   unsigned int dataleft;
      +};
      +
      +void example5_init(void) {
      +   uip_listen(HTONS(80));
      +   uip_listen(HTONS(81));
      +}
      +
      +void example5_app(void) {
      +   struct example5_state *s;
      +   s = (struct example5_state)uip_conn->appstate;
      +   
      +   if(uip_connected()) {
      +      switch(uip_conn->lport) {
      +      case HTONS(80):
      +         s->dataptr = data_port_80;
      +         s->dataleft = datalen_port_80;
      +         break;
      +      case HTONS(81):
      +         s->dataptr = data_port_81;
      +         s->dataleft = datalen_port_81;
      +         break;
      +      }
      +      uip_send(s->dataptr, s->dataleft);
      +      return;      
      +   }
      +
      +   if(uip_acked()) {
      +      if(s->dataleft < uip_mss()) {
      +         uip_close();
      +         return;
      +      }
      +      s->dataptr += uip_conn->len;
      +      s->dataleft -= uip_conn->len;
      +      uip_send(s->dataptr, s->dataleft);      
      +   }
      +}
      +

      +The application state consists of a pointer to the data that should be sent and the size of the data that is left to send. When a remote host connects to the application, the local port number is used to determine which file to send. The first chunk of data is sent using uip_send(). uIP makes sure that no more than MSS bytes of data is actually sent, even though s->dataleft may be larger than the MSS.

      +The application is driven by incoming acknowledgments. When data has been acknowledged, new data can be sent. If there is no more data to send, the connection is closed using uip_close().

      +Structured application program design

      +When writing larger programs using uIP it is useful to be able to utilize the uIP API in a structured way. The following example provides a structured design that has showed itself to be useful for writing larger protocol implementations than the previous examples showed here. The program is divided into an uIP event handler function that calls seven application handler functions that process new data, act on acknowledged data, send new data, deal with connection establishment or closure events and handle errors. The functions are called newdata(), acked(), senddata(), connected(), closed(), aborted(), and timedout(), and needs to be written specifically for the protocol that is being implemented.

      +The uIP event handler function is shown below.

      +

      void example6_app(void) {
      +  if(uip_aborted()) {
      +    aborted();
      +  }
      +  if(uip_timedout()) {
      +    timedout();
      +  }
      +  if(uip_closed()) {
      +    closed();
      +  }
      +  if(uip_connected()) {
      +    connected();
      +  }
      +  if(uip_acked()) {
      +    acked();
      +  }
      +  if(uip_newdata()) {
      +    newdata();
      +  }
      +  if(uip_rexmit() ||
      +     uip_newdata() ||
      +     uip_acked() ||
      +     uip_connected() ||
      +     uip_poll()) {
      +    senddata();
      +  }
      +}
      +

      +The function starts with dealing with any error conditions that might have happened by checking if uip_aborted() or uip_timedout() are true. If so, the appropriate error function is called. Also, if the connection has been closed, the closed() function is called to the it deal with the event.

      +Next, the function checks if the connection has just been established by checking if uip_connected() is true. The connected() function is called and is supposed to do whatever needs to be done when the connection is established, such as intializing the application state for the connection. Since it may be the case that data should be sent out, the senddata() function is called to deal with the outgoing data.

      +The following very simple application serves as an example of how the application handler functions might look. This application simply waits for any data to arrive on the connection, and responds to the data by sending out the message "Hello world!". To illustrate how to develop an application state machine, this message is sent in two parts, first the "Hello" part and then the "world!" part.

      +

      #define STATE_WAITING 0
      +#define STATE_HELLO   1
      +#define STATE_WORLD   2
      +
      +struct example6_state {
      +  u8_t state;
      +  char *textptr;
      +  int  textlen;
      +};
      +
      +static void aborted(void) {}
      +static void timedout(void) {}
      +static void closed(void) {}
      +
      +static void connected(void) {
      +  struct example6_state *s = (struct example6_state *)uip_conn->appstate;
      +
      +  s->state   = STATE_WAITING;
      +  s->textlen = 0;
      +}
      +
      +static void newdata(void) {
      +  struct example6_state *s = (struct example6_state *)uip_conn->appstate;
      +
      +  if(s->state == STATE_WAITING) {
      +    s->state   = STATE_HELLO;
      +    s->textptr = "Hello ";
      +    s->textlen = 6;
      +  }
      +}
      +
      +static void acked(void) {
      +  struct example6_state *s = (struct example6_state *)uip_conn->appstate;
      +  
      +  s->textlen -= uip_conn->len;
      +  s->textptr += uip_conn->len;
      +  if(s->textlen == 0) {
      +    switch(s->state) {
      +    case STATE_HELLO:
      +      s->state   = STATE_WORLD;
      +      s->textptr = "world!\n";
      +      s->textlen = 7;
      +      break;
      +    case STATE_WORLD:
      +      uip_close();
      +      break;
      +    }
      +  }
      +}
      +
      +static void senddata(void) {
      +  struct example6_state *s = (struct example6_state *)uip_conn->appstate;
      +
      +  if(s->textlen > 0) {
      +    uip_send(s->textptr, s->textlen);
      +  }
      +}
      +

      +The application state consists of a "state" variable, a "textptr" pointer to a text message and the "textlen" length of the text message. The "state" variable can be either "STATE_WAITING", meaning that the application is waiting for data to arrive from the network, "STATE_HELLO", in which the application is sending the "Hello" part of the message, or "STATE_WORLD", in which the application is sending the "world!" message.

      +The application does not handle errors or connection closing events, and therefore the aborted(), timedout() and closed() functions are implemented as empty functions.

      +The connected() function will be called when a connection has been established, and in this case sets the "state" variable to be "STATE_WAITING" and the "textlen" variable to be zero, indicating that there is no message to be sent out.

      +When new data arrives from the network, the newdata() function will be called by the event handler function. The newdata() function will check if the connection is in the "STATE_WAITING" state, and if so switches to the "STATE_HELLO" state and registers a 6 byte long "Hello " message with the connection. This message will later be sent out by the senddata() function.

      +The acked() function is called whenever data that previously was sent has been acknowleged by the receiving host. This acked() function first reduces the amount of data that is left to send, by subtracting the length of the previously sent data (obtained from "uip_conn->len") from the "textlen" variable, and also adjusts the "textptr" pointer accordingly. It then checks if the "textlen" variable now is zero, which indicates that all data now has been successfully received, and if so changes application state. If the application was in the "STATE_HELLO" state, it switches state to "STATE_WORLD" and sets up a 7 byte "world!\n" message to be sent. If the application was in the "STATE_WORLD" state, it closes the connection.

      +Finally, the senddata() function takes care of actually sending the data that is to be sent. It is called by the event handler function when new data has been received, when data has been acknowledged, when a new connection has been established, when the connection is polled because of inactivity, or when a retransmission should be made. The purpose of the senddata() function is to optionally format the data that is to be sent, and to call the uip_send() function to actually send out the data. In this particular example, the function simply calls uip_send() with the appropriate arguments if data is to be sent, after checking if data should be sent out or not as indicated by the "textlen" variable.

      +It is important to note that the senddata() function never should affect the application state; this should only be done in the acked() and newdata() functions.


      Generated on Tue Oct 7 15:51:00 2003 for uIP 0.9 by + +doxygen +1.3.3
      + + diff --git a/doc/html/modules.html b/doc/html/modules.html new file mode 100644 index 0000000..e694773 --- /dev/null +++ b/doc/html/modules.html @@ -0,0 +1,46 @@ + + +uIP 0.9: Module Index + + + + +

      uIP 0.9 Modules

      Here is a list of all modules: +
      Generated on Tue Oct 7 15:51:51 2003 for uIP 0.9 by + +doxygen +1.3.3
      + + diff --git a/doc/html/tree.html b/doc/html/tree.html new file mode 100644 index 0000000..66dba9c --- /dev/null +++ b/doc/html/tree.html @@ -0,0 +1,191 @@ + + + + + + + TreeView + + + + + + + + diff --git a/doc/mobisys2003.pdf b/doc/mobisys2003.pdf new file mode 100644 index 0000000..f5e7425 Binary files /dev/null and b/doc/mobisys2003.pdf differ diff --git a/doc/uip-doc.txt b/doc/uip-doc.txt new file mode 100644 index 0000000..73d13b0 --- /dev/null +++ b/doc/uip-doc.txt @@ -0,0 +1,911 @@ + +/** +\defgroup uip The uIP TCP/IP stack +@{ +*/ + +/** +\mainpage The uIP TCP/IP stack +\author Adam Dunkels + +The uIP TCP/IP stack is intended to make it possible to communicate +using the TCP/IP protocol suite even on small 8-bit +micro-controllers. Despite being small and simple, uIP do not require +their peers to have complex, full-size stacks, but can communicate +with peers running a similarly light-weight stack. The code size is on +the order of a few kilobytes and RAM usage can be configured to be as +low as a few hundred bytes. + +\section uIPIntroduction uIP introduction + +With the success of the Internet, the TCP/IP protocol suite has become +a global standard for communication. TCP/IP is the underlying protocol +used for web page transfers, e-mail transmissions, file transfers, and +peer-to-peer networking over the Internet. For embedded systems, being +able to run native TCP/IP makes it possible to connect the system +directly to an intranet or even the global Internet. Embedded devices +with full TCP/IP support will be first-class network citizens, thus +being able to fully communicate with other hosts in the network. + +Traditional TCP/IP implementations have required far too much +resources both in terms of code size and memory usage to be useful in +small 8 or 16-bit systems. Code size of a few hundred kilobytes and +RAM requirements of several hundreds of kilobytes have made it +impossible to fit the full TCP/IP stack into systems with a few tens +of kilobytes of RAM and room for less than 100 kilobytes of +code. + +The uIP implementation is designed to have only the absolute minimal +set of features needed for a full TCP/IP stack. It can only handle a +single network interface and contains only a rudimentary UDP +implementation, but focuses on the IP, ICMP and TCP protocols. uIP is +written in the C programming language. + +Many other TCP/IP implementations for small systems assume that the +embedded device always will communicate with a full-scale TCP/IP +implementation running on a workstation-class machine. Under this +assumption, it is possible to remove certain TCP/IP mechanisms that +are very rarely used in such situations. Many of those mechanisms are +essential, however, if the embedded device is to communicate with +another equally limited device, e.g., when running distributed +peer-to-peer services and protocols. uIP is designed to be RFC +compliant in order to let the embedded devices to act as first-class +network citizens. The uIP TCP/IP implementation that is not tailored +for any specific application. + + +\section tcpip TCP/IP communication + +The full TCP/IP suite consists of numerous protocols, ranging from low +level protocols such as ARP which translates IP addresses to MAC +addresses, to application level protocols such as SMTP that is used to +transfer e-mail. The uIP is mostly concerned with the TCP and IP +protocols and upper layer protocols will be referred to as "the +application". Lower layer protocols are often implemented in hardware +or firmware and will be referred to as "the network device" that are +controlled by the network device driver. + +TCP provides a reliable byte stream to the upper layer protocols. It +breaks the byte stream into appropriately sized segments and each +segment is sent in its own IP packet. The IP packets are sent out on +the network by the network device driver. If the destination is not on +the physically connected network, the IP packet is forwarded onto +another network by a router that is situated between the two +networks. If the maximum packet size of the other network is smaller +than the size of the IP packet, the packet is fragmented into smaller +packets by the router. If possible, the size of the TCP segments are +chosen so that fragmentation is minimized. The final recipient of the +packet will have to reassemble any fragmented IP packets before they +can be passed to higher layers. + +The formal requirements for the protocols in the TCP/IP stack is +specified in a number of RFC documents published by the Internet +Engineering Task Force, IETF. Each of the protocols in the stack is +defined in one more RFC documents and RFC1122 collects +all requirements and updates the previous RFCs. + +The RFC1122 requirements can be divided into two categories; those +that deal with the host to host communication and those that deal with +communication between the application and the networking stack. An +example of the first kind is "A TCP MUST be able to receive a TCP +option in any segment" and an example of the second kind is "There +MUST be a mechanism for reporting soft TCP error conditions to the +application." A TCP/IP implementation that violates requirements of +the first kind may not be able to communicate with other TCP/IP +implementations and may even lead to network failures. Violation of +the second kind of requirements will only affect the communication +within the system and will not affect host-to-host communication. + +In uIP, all RFC requirements that affect host-to-host communication +are implemented. However, in order to reduce code size, we have +removed certain mechanisms in the interface between the application +and the stack, such as the soft error reporting mechanism and +dynamically configurable type-of-service bits for TCP +connections. Since there are only very few applications that make use +of those features they can be removed without loss of generality. + +\section memory Memory management + +In the architectures for which uIP is intended, RAM is the most +scarce resource. With only a few kilobytes of RAM available for the +TCP/IP stack to use, mechanisms used in traditional TCP/IP cannot be +directly applied. + + +The uIP stack does not use explicit dynamic memory +allocation. Instead, it uses a single global buffer for holding +packets and has a fixed table for holding connection state. The global +packet buffer is large enough to contain one packet of maximum +size. When a packet arrives from the network, the device driver places +it in the global buffer and calls the TCP/IP stack. If the packet +contains data, the TCP/IP stack will notify the corresponding +application. Because the data in the buffer will be overwritten by the +next incoming packet, the application will either have to act +immediately on the data or copy the data into a secondary buffer for +later processing. The packet buffer will not be overwritten by new +packets before the application has processed the data. Packets that +arrive when the application is processing the data must be queued, +either by the network device or by the device driver. Most single-chip +Ethernet controllers have on-chip buffers that are large enough to +contain at least 4 maximum sized Ethernet frames. Devices that are +handled by the processor, such as RS-232 ports, can copy incoming +bytes to a separate buffer during application processing. If the +buffers are full, the incoming packet is dropped. This will cause +performance degradation, but only when multiple connections are +running in parallel. This is because uIP advertises a very small +receiver window, which means that only a single TCP segment will be in +the network per connection. + +In uIP, the same global packet buffer that is used for incoming +packets is also used for the TCP/IP headers of outgoing data. If the +application sends dynamic data, it may use the parts of the global +packet buffer that are not used for headers as a temporary storage +buffer. To send the data, the application passes a pointer to the data +as well as the length of the data to the stack. The TCP/IP headers are +written into the global buffer and once the headers have been +produced, the device driver sends the headers and the application data +out on the network. The data is not queued for +retransmissions. Instead, the application will have to reproduce the +data if a retransmission is necessary. + +The total amount of memory usage for uIP depends heavily on the +applications of the particular device in which the implementations are +to be run. The memory configuration determines both the amount of +traffic the system should be able to handle and the maximum amount of +simultaneous connections. A device that will be sending large e-mails +while at the same time running a web server with highly dynamic web +pages and multiple simultaneous clients, will require more RAM than a +simple Telnet server. It is possible to run the uIP implementation +with as little as 200 bytes of RAM, but such a configuration will +provide extremely low throughput and will only allow a small number of +simultaneous connections. + +\section api Application program interface (API) + +The Application Program Interface (API) defines the way the +application program interacts with the TCP/IP stack. The most commonly +used API for TCP/IP is the BSD socket API which is used in most Unix +systems and has heavily influenced the Microsoft Windows WinSock +API. Because the socket API uses stop-and-wait semantics, it requires +support from an underlying multitasking operating system. Since the +overhead of task management, context switching and allocation of stack +space for the tasks might be too high in the intended uIP target +architectures, the BSD socket interface is not suitable for our +purposes. + +Instead, uIP uses an event driven interface where the application is +invoked in response to certain events. An application running on top +of uIP is implemented as a C function that is called by uIP in +response to certain events. uIP calls the application when data is +received, when data has been successfully delivered to the other end +of the connection, when a new connection has been set up, or when data +has to be retransmitted. The application is also periodically polled +for new data. The application program provides only one callback +function; it is up to the application to deal with mapping different +network services to different ports and connections. Because the +application is able to act on incoming data and connection requests as +soon as the TCP/IP stack receives the packet, low response times can +be achieved even in low-end systems. + +uIP is different from other TCP/IP stacks in that it requires help +from the application when doing retransmissions. Other TCP/IP stacks +buffer the transmitted data in memory until the data is known to be +successfully delivered to the remote end of the connection. If the +data needs to be retransmitted, the stack takes care of the +retransmission without notifying the application. With this approach, +the data has to be buffered in memory while waiting for an +acknowledgment even if the application might be able to quickly +regenerate the data if a retransmission has to be made. + +In order to reduce memory usage, uIP utilizes the fact that the +application may be able to regenerate sent data and lets the +application take part in retransmissions. uIP does not keep track of +packet contents after they have been sent by the device driver, and +uIP requires that the application takes an active part in performing +the retransmission. When uIP decides that a segment should be +retransmitted, it calls the application with a flag set indicating +that a retransmission is required. The application checks the +retransmission flag and produces the same data that was previously +sent. From the application's standpoint, performing a retransmission +is not different from how the data originally was sent. Therefore the +application can be written in such a way that the same code is used +both for sending data and retransmitting data. Also, it is important +to note that even though the actual retransmission operation is +carried out by the application, it is the responsibility of the stack +to know when the retransmission should be made. Thus the complexity of +the application does not necessarily increase because it takes an +active part in doing retransmissions. + +\subsection appevents Application events + +The application must be implemented as a C function, UIP_APPCALL(), +that uIP calls whenever an event occurs. Each event has a corresponding +test function that is used to distinguish between different +events. The functions are implemented as C macros that will evaluate +to either zero or non-zero. Note that certain events can happen in +conjunction with each other (i.e., new data can arrive at the same +time as data is acknowledged). + +\subsection connstate The connection pointer + +When the application is called by uIP, the global variable uip_conn is +set to point to the uip_conn structure for the connection that +currently is handled, and is called the "current connection". The +fields in the uip_conn structure for the current connection can be +used, e.g., to distinguish between different services, or to check to +which IP address the connection is connected. One typical use would be +to inspect the uip_conn->lport (the local TCP port number) to decide +which service the connection should provide. For instance, an +application might decide to act as an HTTP server if the value of +uip_conn->lport is equal to 80 and act as a TELNET server if the value +is 23. + +\subsection recvdata Receiving data + +If the uIP test function uip_newdata() is non-zero, the remote host of +the connection has sent new data. The uip_appdata pointer point to the +actual data. The size of the data is obtained through the uIP function +uip_datalen(). The data is not buffered by uIP, but will be +overwritten after the application function returns, and the +application will therefor have to either act directly on the incoming +data, or by itself copy the incoming data into a buffer for later +processing. + +\subsection senddata Sending data + +When sending data, uIP adjusts the length of the data sent by the +application according to the available buffer space and the current +TCP window advertised by the receiver. The amount of buffer space is +dictated by the memory configuration. It is therefore possible that +all data sent from the application does not arrive at the receiver, +and the application may use the uip_mss() function to see how much +data that actually will be sent by the stack. + +The application sends data by using the uIP function uip_send(). The +uip_send() function takes two arguments; a pointer to the data to be +sent and the length of the data. If the application needs RAM space +for producing the actual data that should be sent, the packet buffer +(pointed to by the uip_appdata pointer) can be used for this purpose. + +The application can send only one chunk of data at a time on a +connection and it is not possible to call uip_send() more than once +per application invocation; only the data from the last call will be +sent. + +\subsection rexmitdata Retransmitting data + +Retransmissions are driven by the periodic TCP timer. Every time the +periodic timer is invoked, the retransmission timer for each +connection is decremented. If the timer reaches zero, a retransmission +should be made. As uIP does not keep track of packet contents after they have +been sent by the device driver, uIP requires that the +application takes an active part in performing the +retransmission. When uIP decides that a segment should be +retransmitted, the application function is called with the +uip_rexmit() flag set, indicating that a retransmission is +required. + +The application must check the uip_rexmit() flag and produce the same +data that was previously sent. From the application's standpoint, +performing a retransmission is not different from how the data +originally was sent. Therefor, the application can be written in such +a way that the same code is used both for sending data and +retransmitting data. Also, it is important to note that even though +the actual retransmission operation is carried out by the application, +it is the responsibility of the stack to know when the retransmission +should be made. Thus the complexity of the application does not +necessarily increase because it takes an active part in doing +retransmissions. + +\subsection closing Closing connections + +The application closes the current connection by calling the +uip_close() during an application call. This will cause the connection +to be cleanly closed. In order to indicate a fatal error, the +application might want to abort the connection and does so by calling +the uip_abort() function. + +If the connection has been closed by the remote end, the test function +uip_closed() is true. The application may then do any necessary +cleanups. + +\subsection errors Reporting errors + +There are two fatal errors that can happen to a connection, either +that the connection was aborted by the remote host, or that the +connection retransmitted the last data too many times and has been +aborted. uIP reports this by calling the application function. The +application can use the two test functions uip_aborted() and +uip_timedout() to test for those error conditions. + +\subsection polling Polling + +When a connection is idle, uIP polls the application every time the +periodic timer fires. The application uses the test function +uip_poll() to check if it is being polled by uIP. + +The polling event has two purposes. The first is to let the +application periodically know that a connection is idle, which allows +the application to close connections that have been idle for too +long. The other purpose is to let the application send new data that +has been produced. The application can only send data when invoked by +uIP, and therefore the poll event is the only way to send data on an +otherwise idle connection. + +\subsection listen Listening ports + +uIP maintains a list of listening TCP ports. A new port is opened for +listening with the uip_listen() function. When a connection request +arrives on a listening port, uIP creates a new connection and calls +the application function. The test function uip_connected() is true if +the application was invoked because a new connection was created. + +The application can check the lport field in the uip_conn structure to +check to which port the new connection was connected. + +\subsection connect Opening connections + +New connections can be opened from within +uIP by the function uip_connect(). This function +allocates a new connection and sets a flag in the connection state +which will open a TCP connection to the specified IP address and port +the next time the connection is polled by uIP. The uip_connect() +function returns +a pointer to the uip_conn structure for the new +connection. If there are no free connection slots, the function +returns NULL. + +The function uip_ipaddr() may be used to pack an IP address into the +two element 16-bit array used by uIP to represent IP addresses. + +Two examples of usage are shown below. The first example shows how to +open a connection to TCP port 8080 of the remote end of the current +connection. If there are not enough TCP connection slots to allow a +new connection to be opened, the uip_connect() function returns NULL +and the current connection is aborted by uip_abort(). + +\code +void connect_example1_app(void) { + if(uip_connect(uip_conn->ripaddr, HTONS(8080)) == NULL) { + uip_abort(); + } +} +\endcode + +The second example shows how to open a new connection to a specific IP +address. No error checks are made in this example. + +\code +void connect_example2(void) { + u16_t ipaddr[2]; + + uip_ipaddr(ipaddr, 192,168,0,1); + uip_connect(ipaddr, HTONS(8080)); +} +\endcode + +\section drivers uIP device drivers + +From the network device driver's standpoint, uIP consists of two C +functions: uip_input() and uip_periodic(). The uip_input() function +should be called by the device driver when an IP packet has been +received and put into the uip_buf packet buffer. The uip_input() +function will process the packet, and when it returns an outbound +packet may have been placed in the same uip_buf packet buffer +(indicated by the uip_len variable being non-zero). The device driver +should then send out this packet onto the network. + +The uip_periodic() function should be invoked periodically once per +connection by the device driver, typically one per second. This +function is used by uIP to drive protocol timers and retransmissions, +and when it returns it may have placed an outbound packet in the +uip_buf buffer. + +\section arch Architecture specific functions + +uIP requires a few functions to be implemented specifically for the +architecture on which uIP is intended to run. These functions should +be hand-tuned for the particular architecture, but generic C +implementations are given as part of the uIP distribution. + +\subsection checksums Checksum calculation + +The TCP and IP protocols implement a checksum that covers the data and +header portions of the TCP and IP packets. Since the calculation of +this checksum is made over all bytes in every packet being sent and +received it is important that the function that calculates the +checksum is efficient. Most often, this means that the checksum +calculation must be fine-tuned for the particular architecture on +which the uIP stack runs. + +Because of this, uIP does not implement a generic checksum function, +but leaves this to the architecture specific files which must +implement the two functions uip_ipchksum() and uip_tcpchksum(). The +checksum calculations in those functions can be written in highly +optimized assembler rather than generic C code. + +An example C implementation of the checksum function is provided in +the uIP distribution. + +\subsection longarith 32-bit arithmetic + +The TCP protocol uses 32-bit sequence numbers, and a TCP +implementation will have to do a number of 32-bit additions as part of +the normal protocol processing. Since 32-bit arithmetic is not +natively available on many of the platforms for which uIP is intended, +uIP leaves the 32-bit additions to be implemented by the architecture +specific module and does not make use of any 32-bit arithmetic in the +main code base. + +The architecture specific code must implement a function uip_add32() +which does a 32-bit addition and stores the result in a global +variable uip_acc32. + +\section examples Examples + +This section presents a number of very simple uIP applications. The +uIP code distribution contains several more complex applications. + +\subsection example1 A very simple application + +This first example shows a very simple application. The application +listens for incoming connections on port 1234. When a connection has +been established, the application replies to all data sent to it by +saying "ok" + +The implementation of this application is shown below. The application +is initialized with the function called example1_init() and the uIP +callback function is called example1_app(). For this application, the +configuration variable UIP_APPCALL should be defined to be +example1_app(). + +\code +void example1_init(void) { + uip_listen(HTONS(1234)); +} + +void example1_app(void) { + if(uip_newdata() || uip_rexmit()) { + uip_send("ok\n", 3); + } +} +\endcode + +The initialization function calls the uIP function uip_listen() to +register a listening port. The actual application function +example1_app() uses the test functions uip_newdata() and uip_rexmit() +to determine why it was called. If the application was called because +the remote end has sent it data, it responds with an "ok". If the +application function was called because data was lost in the network +and has to be retransmitted, it also sends an "ok". Note that this +example actually shows a complete uIP application. It is not required +for an application to deal with all types of events such as +uip_connected() or uip_timedout(). + +\subsection example2 A more advanced application + +This second example is slightly more advanced than the previous one, +and shows how the application state field in the uip_conn structure is +used. + +This application is similar to the first application in that it +listens to a port for incoming connections and responds to data sent +to it with a single "ok". The big difference is that this application +prints out a welcoming "Welcome!" message when the connection has been +established. + +This seemingly small change of operation makes a big difference in how +the application is implemented. The reason for the increase in +complexity is that if data should be lost in the network, the +application must know what data to retransmit. If the "Welcome!" +message was lost, the application must retransmit the welcome and if +one of the "ok" messages is lost, the application must send a new +"ok". + +The application knows that as long as the "Welcome!" message has not +been acknowledged by the remote host, it might have been dropped in +the network. But once the remote host has sent an acknowledgment +back, the application can be sure that the welcome has been received +and knows that any lost data must be an "ok" message. Thus the +application can be in either of two states: either in the WELCOME-SENT +state where the "Welcome!" has been sent but not acknowledged, or in +the WELCOME-ACKED state where the "Welcome!" has been acknowledged. + +When a remote host connects to the application, the application sends +the "Welcome!" message and sets it's state to WELCOME-SENT. When the +welcome message is acknowledged, the application moves to the +WELCOME-ACKED state. If the application receives any new data from the +remote host, it responds by sending an "ok" back. + +If the application is requested to retransmit the last message, it +looks at in which state the application is. If the application is in +the WELCOME-SENT state, it sends a "Welcome!" message since it +knows that the previous welcome message hasn't been acknowledged. If +the application is in the WELCOME-ACKED state, it knows that the last +message was an "ok" message and sends such a message. + +The implementation of this application is seen below. This +configuration settings for the application is follows after its +implementation. + +\code +struct example2_state { + enum {WELCOME_SENT, WELCOME_ACKED} state; +}; + +void example2_init(void) { + uip_listen(HTONS(2345)); +} + +void example2_app(void) { + struct example2_state *s; + + s = (struct example2_state *)uip_conn->appstate; + + if(uip_connected()) { + s->state = WELCOME_SENT; + uip_send("Welcome!\n", 9); + return; + } + + if(uip_acked() && s->state == WELCOME_SENT) { + s->state = WELCOME_ACKED; + } + + if(uip_newdata()) { + uip_send("ok\n", 3); + } + + if(uip_rexmit()) { + switch(s->state) { + case WELCOME_SENT: + uip_send("Welcome!\n", 9); + break; + case WELCOME_ACKED: + uip_send("ok\n", 3); + break; + } + } +} +\endcode + +The configuration for the application: + +\code +#define UIP_APPCALL example2_app +#define UIP_APPSTATE_SIZE sizeof(struct example2_state) +\endcode + +\subsection example3 Differentiating between applications + +If the system should run multiple applications, one technique to +differentiate between them is to use the TCP port number of either the +remote end or the local end of the connection. The example below shows +how the two examples above can be combined into one application. + +\code +void example3_init(void) { + example1_init(); + example2_init(); +} + +void example3_app(void) { + switch(uip_conn->lport) { + case HTONS(1234): + example1_app(); + break; + case HTONS(2345): + example2_app(); + break; + } +} +\endcode + +\subsection example4 Utilizing TCP flow control + +This example shows a simple application that connects to a host, sends +an HTTP request for a file and downloads it to a slow device such a +disk drive. This shows how to use the flow control functions of uIP. + +\code +void example4_init(void) { + u16_t ipaddr[2]; + uip_ipaddr(ipaddr, 192,168,0,1); + uip_connect(ipaddr, HTONS(80)); +} + +void example4_app(void) { + if(uip_connected() || uip_rexmit()) { + uip_send("GET /file HTTP/1.0\r\nServer:192.186.0.1\r\n\r\n", + 48); + return; + } + + if(uip_newdata()) { + device_enqueue(uip_appdata, uip_datalen()); + if(device_queue_full()) { + uip_stop(); + } + } + + if(uip_poll() && uip_stopped()) { + if(!device_queue_full()) { + uip_restart(); + } + } +} +\endcode + +When the connection has been established, an HTTP request is sent to +the server. Since this is the only data that is sent, the application +knows that if it needs to retransmit any data, it is that request that +should be retransmitted. It is therefore possible to combine these two +events as is done in the example. + +When the application receives new data from the remote host, it sends +this data to the device by using the function device_enqueue(). It is +important to note that this example assumes that this function copies +the data into its own buffers. The data in the uip_appdata buffer will +be overwritten by the next incoming packet. + +If the device's queue is full, the application stops the data from the +remote host by calling the uIP function uip_stop(). The application +can then be sure that it will not receive any new data until +uip_restart() is called. The application polling event is used to +check if the device's queue is no longer full and if so, the data flow +is restarted with uip_restart(). + +\subsection example5 A simple web server + +This example shows a very simple file server application that listens +to two ports and uses the port number to determine which file to +send. If the files are properly formatted, this simple application can +be used as a web server with static pages. The implementation follows. + +\code +struct example5_state { + char *dataptr; + unsigned int dataleft; +}; + +void example5_init(void) { + uip_listen(HTONS(80)); + uip_listen(HTONS(81)); +} + +void example5_app(void) { + struct example5_state *s; + s = (struct example5_state)uip_conn->appstate; + + if(uip_connected()) { + switch(uip_conn->lport) { + case HTONS(80): + s->dataptr = data_port_80; + s->dataleft = datalen_port_80; + break; + case HTONS(81): + s->dataptr = data_port_81; + s->dataleft = datalen_port_81; + break; + } + uip_send(s->dataptr, s->dataleft); + return; + } + + if(uip_acked()) { + if(s->dataleft < uip_mss()) { + uip_close(); + return; + } + s->dataptr += uip_conn->len; + s->dataleft -= uip_conn->len; + uip_send(s->dataptr, s->dataleft); + } +} +\endcode + +The application state consists of a pointer to the data that should be +sent and the size of the data that is left to send. When a remote host +connects to the application, the local port number is used to +determine which file to send. The first chunk of data is sent using +uip_send(). uIP makes sure that no more than MSS bytes of data is +actually sent, even though s->dataleft may be larger than the MSS. + +The application is driven by incoming acknowledgments. When data has +been acknowledged, new data can be sent. If there is no more data to +send, the connection is closed using uip_close(). + +\subsection example6 Structured application program design + +When writing larger programs using uIP it is useful to be able to +utilize the uIP API in a structured way. The following example +provides a structured design that has showed itself to be useful for +writing larger protocol implementations than the previous examples +showed here. The program is divided into an uIP event handler function +that calls seven application handler functions that process new data, +act on acknowledged data, send new data, deal with connection +establishment or closure events and handle errors. The functions are +called newdata(), acked(), senddata(), connected(), closed(), +aborted(), and timedout(), and needs to be written specifically for +the protocol that is being implemented. + +The uIP event handler function is shown below. + +\code +void example6_app(void) { + if(uip_aborted()) { + aborted(); + } + if(uip_timedout()) { + timedout(); + } + if(uip_closed()) { + closed(); + } + if(uip_connected()) { + connected(); + } + if(uip_acked()) { + acked(); + } + if(uip_newdata()) { + newdata(); + } + if(uip_rexmit() || + uip_newdata() || + uip_acked() || + uip_connected() || + uip_poll()) { + senddata(); + } +} +\endcode + +The function starts with dealing with any error conditions that might +have happened by checking if uip_aborted() or uip_timedout() are +true. If so, the appropriate error function is called. Also, if the +connection has been closed, the closed() function is called to the it +deal with the event. + +Next, the function checks if the connection has just been established +by checking if uip_connected() is true. The connected() function is +called and is supposed to do whatever needs to be done when the +connection is established, such as intializing the application state +for the connection. Since it may be the case that data should be sent +out, the senddata() function is called to deal with the outgoing data. + +The following very simple application serves as an example of how the +application handler functions might look. This application simply +waits for any data to arrive on the connection, and responds to the +data by sending out the message "Hello world!". To illustrate how to +develop an application state machine, this message is sent in two +parts, first the "Hello" part and then the "world!" part. + +\code +#define STATE_WAITING 0 +#define STATE_HELLO 1 +#define STATE_WORLD 2 + +struct example6_state { + u8_t state; + char *textptr; + int textlen; +}; + +static void aborted(void) {} +static void timedout(void) {} +static void closed(void) {} + +static void connected(void) { + struct example6_state *s = (struct example6_state *)uip_conn->appstate; + + s->state = STATE_WAITING; + s->textlen = 0; +} + +static void newdata(void) { + struct example6_state *s = (struct example6_state *)uip_conn->appstate; + + if(s->state == STATE_WAITING) { + s->state = STATE_HELLO; + s->textptr = "Hello "; + s->textlen = 6; + } +} + +static void acked(void) { + struct example6_state *s = (struct example6_state *)uip_conn->appstate; + + s->textlen -= uip_conn->len; + s->textptr += uip_conn->len; + if(s->textlen == 0) { + switch(s->state) { + case STATE_HELLO: + s->state = STATE_WORLD; + s->textptr = "world!\n"; + s->textlen = 7; + break; + case STATE_WORLD: + uip_close(); + break; + } + } +} + +static void senddata(void) { + struct example6_state *s = (struct example6_state *)uip_conn->appstate; + + if(s->textlen > 0) { + uip_send(s->textptr, s->textlen); + } +} +\endcode + +The application state consists of a "state" variable, a "textptr" +pointer to a text message and the "textlen" length of the text +message. The "state" variable can be either "STATE_WAITING", meaning +that the application is waiting for data to arrive from the network, +"STATE_HELLO", in which the application is sending the "Hello" part of +the message, or "STATE_WORLD", in which the application is sending the +"world!" message. + +The application does not handle errors or connection closing events, +and therefore the aborted(), timedout() and closed() functions are +implemented as empty functions. + +The connected() function will be called when a connection has been +established, and in this case sets the "state" variable to be +"STATE_WAITING" and the "textlen" variable to be zero, indicating that +there is no message to be sent out. + +When new data arrives from the network, the newdata() function will be +called by the event handler function. The newdata() function will +check if the connection is in the "STATE_WAITING" state, and if so +switches to the "STATE_HELLO" state and registers a 6 byte long "Hello +" message with the connection. This message will later be sent out by +the senddata() function. + +The acked() function is called whenever data that previously was sent +has been acknowleged by the receiving host. This acked() function +first reduces the amount of data that is left to send, by subtracting +the length of the previously sent data (obtained from "uip_conn->len") +from the "textlen" variable, and also adjusts the "textptr" pointer +accordingly. It then checks if the "textlen" variable now is zero, +which indicates that all data now has been successfully received, and +if so changes application state. If the application was in the +"STATE_HELLO" state, it switches state to "STATE_WORLD" and sets up a +7 byte "world!\n" message to be sent. If the application was in the +"STATE_WORLD" state, it closes the connection. + +Finally, the senddata() function takes care of actually sending the +data that is to be sent. It is called by the event handler function +when new data has been received, when data has been acknowledged, when +a new connection has been established, when the connection is polled +because of inactivity, or when a retransmission should be made. The +purpose of the senddata() function is to optionally format the data +that is to be sent, and to call the uip_send() function to actually +send out the data. In this particular example, the function simply +calls uip_send() with the appropriate arguments if data is to be sent, +after checking if data should be sent out or not as indicated by the +"textlen" variable. + +It is important to note that the senddata() function never should +affect the application state; this should only be done in the acked() +and newdata() functions. + +*/ + + +/** @} */ + +/** +\defgroup exampleapps Example applications +@{ + +The uIP distribution contains a number of example applications that +can be either used directory or studied when learning to develop +applications for uIP. + +*/ + +/** @} */ \ No newline at end of file diff --git a/doc/uip-refman.pdf b/doc/uip-refman.pdf new file mode 100644 index 0000000..cd91aff Binary files /dev/null and b/doc/uip-refman.pdf differ diff --git a/cc65/rs232dev.c b/uip/slipdev.c similarity index 55% rename from cc65/rs232dev.c rename to uip/slipdev.c index 43de617..4e25b51 100644 --- a/cc65/rs232dev.c +++ b/uip/slipdev.c @@ -1,3 +1,28 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup slip Serial Line IP (SLIP) protocol + * @{ + * + * The SLIP protocol is a very simple way to transmit IP packets over + * a serial line. It does not provide any framing or error control, + * and is therefore not very widely used today. + * + * This SLIP implementation requires two functions for accessing the + * serial device: slipdev_char_poll() and slipdev_char_put(). These + * must be implemented specifically for the system on which the SLIP + * protocol is to be run. + */ + +/** + * \file + * SLIP protocol implementation + * \author Adam Dunkels + */ + /* * Copyright (c) 2001, Adam Dunkels. * All rights reserved. @@ -10,10 +35,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,31 +53,19 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: rs232dev.c,v 1.1 2001/11/20 20:49:45 adam Exp $ + * $Id: slipdev.c,v 1.1.2.3 2003/10/07 13:23:01 adam Exp $ * */ /* * This is a generic implementation of the SLIP protocol over an RS232 - * (serial) device. While initially intented for the C64, the code can - * easily be ported to other platforms as well. + * (serial) device. * * Huge thanks to Ullrich von Bassewitz of cc65 fame for * and endless supply of bugfixes, insightsful comments and * suggestions, and improvements to this code! */ -#include -#include -#include - - /* This will include the system specific header files as well */ -#if defined(__CBM__) -# include -#elif defined(__ATARI__) -# include -#endif - #include "uip.h" #define SLIP_END 0300 @@ -63,123 +73,73 @@ #define SLIP_ESC_END 0334 #define SLIP_ESC_ESC 0335 +static u8_t slip_buf[UIP_BUFSIZE]; -#define SIO_RECV(c) while(rs232_get(&c) == RS_ERR_NO_DATA) -#define SIO_POLL(c) (rs232_get(&c) != RS_ERR_NO_DATA) -#define SIO_SEND(c) rs232_put(c) - -#define MAX_SIZE UIP_BUFSIZE - -static u8_t slip_buf[MAX_SIZE]; - -#if MAX_SIZE > 255 static u16_t len, tmplen; -#else -static u8_t len, tmplen; -#endif /* MAX_SIZE > 255 */ - -#if 0 -#define printf(x) -#else -#include -#endif - +static u8_t lastc; /*-----------------------------------------------------------------------------------*/ -static void -rs232_err(char err) -{ - switch(err) { - case RS_ERR_OK: - printf("RS232 OK\n"); - break; - case RS_ERR_NOT_INITIALIZED: - printf("RS232 not initialized\n"); - break; - case RS_ERR_BAUD_TOO_FAST: - printf("RS232 baud too fast\n"); - break; - case RS_ERR_BAUD_NOT_AVAIL: - printf("RS232 baud rate not available\n"); - break; - case RS_ERR_NO_DATA: - printf("RS232 nothing to read\n"); - break; - case RS_ERR_OVERFLOW: - printf("RS232 overflow\n"); - break; - } - -} -/*-----------------------------------------------------------------------------------*/ -/* - * rs232dev_send(): +/** + * Send the packet in the uip_buf and uip_appdata buffers using the + * SLIP protocol. * - * Sends the packet in the uip_buf and uip_appdata buffers. The first - * 40 bytes of the packet (the IP and TCP headers) are read from the - * uip_buf buffer, and the following bytes (the application data) are - * read from the uip_appdata buffer. + * The first 40 bytes of the packet (the IP and TCP headers) are read + * from the uip_buf buffer, and the following bytes (the application + * data) are read from the uip_appdata buffer. * */ /*-----------------------------------------------------------------------------------*/ void -rs232dev_send(void) +slipdev_send(void) { -#if MAX_SIZE > 255 u16_t i; -#else - u8_t i; -#endif /* MAX_SIZE > 255 */ u8_t *ptr; u8_t c; - SIO_SEND(SLIP_END); + slipdev_char_put(SLIP_END); ptr = uip_buf; for(i = 0; i < uip_len; ++i) { if(i == 40) { - ptr = uip_appdata; + ptr = (char *)uip_appdata; } c = *ptr++; switch(c) { case SLIP_END: - SIO_SEND(SLIP_ESC); - SIO_SEND(SLIP_ESC_END); + slipdev_char_put(SLIP_ESC); + slipdev_char_put(SLIP_ESC_END); break; case SLIP_ESC: - SIO_SEND(SLIP_ESC); - SIO_SEND(SLIP_ESC_ESC); + slipdev_char_put(SLIP_ESC); + slipdev_char_put(SLIP_ESC_ESC); break; default: - SIO_SEND(c); + slipdev_char_put(c); break; } } - SIO_SEND(SLIP_END); + slipdev_char_put(SLIP_END); } /*-----------------------------------------------------------------------------------*/ -/* - * rs232dev_poll(): +/** + * Poll the SLIP device for an available packet. * - * Read all avaliable bytes from the RS232 interface into the slip_buf - * buffer. If no more bytes are avaliable, it returns with 0 to - * indicate that no packet was immediately ready. When a full packet - * has been read into the buffer, the packet is copied into the - * uip_buf buffer and the length of the packet is returned. + * This function will poll the SLIP device to see if a packet is + * available. It uses a buffer in which all avaliable bytes from the + * RS232 interface are read into. When a full packet has been read + * into the buffer, the packet is copied into the uip_buf buffer and + * the length of the packet is returned. * + * \return The length of the packet placed in the uip_buf buffer, or + * zero if no packet is available. */ /*-----------------------------------------------------------------------------------*/ -#if MAX_SIZE > 255 u16_t -#else -u8_t -#endif /* MAX_SIZE > 255 */ -rs232dev_poll(void) +slipdev_poll(void) { u8_t c; - static u8_t lastc; - while(SIO_POLL(c)) { + while(slipdev_char_poll(c)) { switch(c) { case SLIP_ESC: lastc = c; @@ -211,11 +171,10 @@ rs232dev_poll(void) lastc = c; } - slip_buf[len] = c; ++len; - if(len > MAX_SIZE) { + if(len > UIP_BUFSIZE) { len = 0; } @@ -225,25 +184,19 @@ rs232dev_poll(void) return 0; } /*-----------------------------------------------------------------------------------*/ -/* - * rs232dev_init(): - * - * Initializes the RS232 device and sets the parameters of the device. +/** + * Initialize the SLIP module. * + * This function does not initialize the underlying RS232 device, but + * only the SLIP part. */ /*-----------------------------------------------------------------------------------*/ void -rs232dev_init(void) +slipdev_init(void) { - char err; - - err = rs232_init(0); - rs232_err(err); - err = rs232_params(RS_BAUD_9600, RS_PAR_NONE); - rs232_err(err); - - len = 0; - - return; + lastc = len = 0; } /*-----------------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ diff --git a/cc65/main.c b/uip/slipdev.h similarity index 50% rename from cc65/main.c rename to uip/slipdev.h index 8f91969..b040b50 100644 --- a/cc65/main.c +++ b/uip/slipdev.h @@ -1,3 +1,14 @@ +/** + * \addtogroup slip + * @{ + */ + +/** + * \file + * SLIP header file. + * \author Adam Dunkels + */ + /* * Copyright (c) 2001, Adam Dunkels. * All rights reserved. @@ -10,10 +21,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,60 +39,50 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: main.c,v 1.1 2001/11/20 20:49:45 adam Exp $ + * $Id: slipdev.h,v 1.1.2.3 2003/10/06 22:42:51 adam Exp $ * */ +#ifndef __SLIPDEV_H__ +#define __SLIPDEV_H__ #include "uip.h" -#include "rs232dev.h" -#include "httpd.h" -#include -#include <6502.h> -#include -#include -#include +/** + * Put a character on the serial device. + * + * This function is used by the SLIP implementation to put a character + * on the serial device. It must be implemented specifically for the + * system on which the SLIP implementation is to be run. + * + * \param c The character to be put on the serial device. + */ +void slipdev_char_put(u8_t c); -/*-----------------------------------------------------------------------------------*/ -void -main(void) -{ - u8_t i; - u16_t start, current; - - rs232dev_init(); - uip_init(); - httpd_init(); +/** + * Poll the serial device for a character. + * + * This function is used by the SLIP implementation to poll the serial + * device for a character. It must be implemented specifically for the + * system on which the SLIP implementation is to be run. + * + * The function should return immediately regardless if a character is + * available or not. If a character is available it should be placed + * at the memory location pointed to by the pointer supplied by the + * arguement c. + * + * \param c A pointer to a byte that is filled in by the function with + * the received character, if available. + * + * \retval 0 If no character is available. + * \retval Non-zero If a character is available. + */ +u8_t slipdev_char_poll(u8_t *c); - printf("uIP TCP/IP stack and web server running\n"); - printf("Press any key to stop.\n"); +void slipdev_init(void); +void slipdev_send(void); +u16_t slipdev_poll(void); - - start = clock(); - - while(!kbhit()) { - uip_len = rs232dev_poll(); - if(uip_len > 0) { - uip_process(UIP_DATA); - if(uip_len > 0) { - rs232dev_send(); - } - } - current = clock(); - if((int)(current - start) >= CLK_TCK) { - for(i = 0; i < UIP_CONNS; ++i) { - uip_periodic(i); - if(uip_len > 0) { - rs232dev_send(); - } - } - start = current; - } - } +#endif /* __SLIPDEV_H__ */ - rs232_done(); - (void)cgetc(); - printf("TCP/IP stack and web server stopped.\n"); -} -/*-----------------------------------------------------------------------------------*/ +/** @} */ diff --git a/uip/uip.c b/uip/uip.c index 2d6b2ce..120c48e 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -1,5 +1,16 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \file + * The uIP TCP/IP stack code. + * \author Adam Dunkels + */ + /* - * Copyright (c) 2001-2002, Adam Dunkels. + * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +21,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +39,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip.c,v 1.34 2002/01/15 17:54:54 adam Exp $ + * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ * */ @@ -41,18 +49,19 @@ some basic ICMP stuff). The implementation couples the IP, TCP and the application layers very tightly. To keep the size of the compiled code down, this code also features heavy usage of the goto statement. -The principle is that we have a small buffer, called the uip_buf, in which -the device driver puts an incoming packet. The TCP/IP stack parses the -headers in the packet, and calls upon the application. If the remote -host has sent data to the application, this data is present in the uip_buf -and the application read the data from there. It is up to the -application to put this data into a byte stream if needed. The +The principle is that we have a small buffer, called the uip_buf, in +which the device driver puts an incoming packet. The TCP/IP stack +parses the headers in the packet, and calls upon the application. If +the remote host has sent data to the application, this data is present +in the uip_buf and the application read the data from there. It is up +to the application to put this data into a byte stream if needed. The application will not be fed with data that is out of sequence. If the application whishes to send data to the peer, it should put its -data into the uip_buf, 40 bytes from the start of the buffer. The TCP/IP -stack will calculate the checksums, and fill in the necessary header -fields and finally send the packet back to the peer. */ +data into the uip_buf, 40 bytes from the start of the buffer. The +TCP/IP stack will calculate the checksums, and fill in the necessary +header fields and finally send the packet back to the peer. +*/ #include "uip.h" #include "uipopt.h" @@ -61,18 +70,40 @@ fields and finally send the packet back to the peer. */ /*-----------------------------------------------------------------------------------*/ /* Variable definitions. */ -u8_t uip_buf[UIP_BUFSIZE]; /* The packet buffer that contains + +/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */ +#if UIP_FIXEDADDR > 0 +const u16_t uip_hostaddr[2] = + {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), + HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; +const u16_t uip_arp_draddr[2] = + {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), + HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; +const u16_t uip_arp_netmask[2] = + {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), + HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; +#else +u16_t uip_hostaddr[2]; +u16_t uip_arp_draddr[2], uip_arp_netmask[2]; +#endif /* UIP_FIXEDADDR */ + +u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains incoming packets. */ volatile u8_t *uip_appdata; /* The uip_appdata pointer points to application data. */ +volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the + application data which is to be sent. */ +#if UIP_URGDATA > 0 +volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to + urgent data (out-of-band data), if + present. */ +volatile u8_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ -#if UIP_BUFSIZE > 255 -volatile u16_t uip_len; /* The uip_len is either 8 or 16 bits, +volatile u16_t uip_len, uip_slen; + /* The uip_len is either 8 or 16 bits, depending on the maximum packet size. */ -#else -volatile u8_t uip_len; -#endif /* UIP_BUFSIZE > 255 */ volatile u8_t uip_flags; /* The uip_flags variable is used for communication between the TCP/IP stack @@ -86,6 +117,10 @@ struct uip_conn uip_conns[UIP_CONNS]; u16_t uip_listenports[UIP_LISTENPORTS]; /* The uip_listenports list all currently listning ports. */ +#if UIP_UDP +struct uip_udp_conn *uip_udp_conn; +struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ static u16_t ipid; /* Ths ipid variable is an increasing @@ -101,44 +136,27 @@ static u16_t lastport; /* Keeps track of the last port used for #endif /* UIP_ACTIVE_OPEN */ /* Temporary variables. */ +volatile u8_t uip_acc32[4]; static u8_t c, opt; -static u16_t tmpport; +static u16_t tmp16; /* Structures and definitions. */ -typedef struct { - /* IP header. */ - u8_t vhl, - tos, - len[2], - ipid[2], - ipoffset[2], - ttl, - proto; - u16_t ipchksum; - u16_t srcipaddr[2], - destipaddr[2]; - /* ICMP (echo) header. */ - u8_t type, icode; - u16_t icmpchksum; - u16_t id, seqno; -} ipicmphdr; - #define TCP_FIN 0x01 #define TCP_SYN 0x02 #define TCP_RST 0x04 #define TCP_PSH 0x08 #define TCP_ACK 0x10 #define TCP_URG 0x20 - -#define IP_PROTO_ICMP 1 -#define IP_PROTO_TCP 6 +#define TCP_CTL 0x3f #define ICMP_ECHO_REPLY 0 #define ICMP_ECHO 8 /* Macros. */ #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define ICMPBUF ((ipicmphdr *)&uip_buf[UIP_LLH_LEN]) +#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) +#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) #if UIP_STATISTICS == 1 struct uip_stats uip_stat; @@ -148,7 +166,9 @@ struct uip_stats uip_stat; #endif /* UIP_STATISTICS == 1 */ #if UIP_LOGGING == 1 -#define UIP_LOG(m) printf("%s\n", m) +#include +void uip_log(char *msg); +#define UIP_LOG(m) uip_log(m) #else #define UIP_LOG(m) #endif /* UIP_LOGGING == 1 */ @@ -166,13 +186,94 @@ uip_init(void) #if UIP_ACTIVE_OPEN lastport = 1024; #endif /* UIP_ACTIVE_OPEN */ + +#if UIP_UDP + for(c = 0; c < UIP_UDP_CONNS; ++c) { + uip_udp_conns[c].lport = 0; + } +#endif /* UIP_UDP */ + + + /* IPv4 initialization. */ +#if UIP_FIXEDADDR == 0 + uip_hostaddr[0] = uip_hostaddr[1] = 0; +#endif /* UIP_FIXEDADDR */ + } /*-----------------------------------------------------------------------------------*/ #if UIP_ACTIVE_OPEN struct uip_conn * uip_connect(u16_t *ripaddr, u16_t rport) { - struct uip_conn *conn; + register struct uip_conn *conn, *cconn; + + /* Find an unused local port. */ + again: + ++lastport; + + if(lastport >= 32000) { + lastport = 4096; + } + + /* Check if this port is already in use, and if so try to find + another one. */ + for(c = 0; c < UIP_CONNS; ++c) { + conn = &uip_conns[c]; + if(conn->tcpstateflags != CLOSED && + conn->lport == htons(lastport)) { + goto again; + } + } + + + conn = 0; + for(c = 0; c < UIP_CONNS; ++c) { + cconn = &uip_conns[c]; + if(cconn->tcpstateflags == CLOSED) { + conn = cconn; + break; + } + if(cconn->tcpstateflags == TIME_WAIT) { + if(conn == 0 || + cconn->timer > uip_conn->timer) { + conn = cconn; + } + } + } + + if(conn == 0) { + return 0; + } + + conn->tcpstateflags = SYN_SENT; + + conn->snd_nxt[0] = iss[0]; + conn->snd_nxt[1] = iss[1]; + conn->snd_nxt[2] = iss[2]; + conn->snd_nxt[3] = iss[3]; + + conn->initialmss = conn->mss = UIP_TCP_MSS; + + conn->len = 1; /* TCP length of the SYN is one. */ + conn->nrtx = 0; + conn->timer = 1; /* Send the SYN next time around. */ + conn->rto = UIP_RTO; + conn->sa = 0; + conn->sv = 16; + conn->lport = htons(lastport); + conn->rport = rport; + conn->ripaddr[0] = ripaddr[0]; + conn->ripaddr[1] = ripaddr[1]; + + return conn; +} +#endif /* UIP_ACTIVE_OPEN */ +/*-----------------------------------------------------------------------------------*/ +#if UIP_UDP +struct uip_udp_conn * +uip_udp_new(u16_t *ripaddr, u16_t rport) +{ + register struct uip_udp_conn *conn; /* Find an unused local port. */ again: @@ -182,71 +283,214 @@ uip_connect(u16_t *ripaddr, u16_t rport) lastport = 4096; } - for(c = 0; c < UIP_CONNS; ++c) { - if(uip_conns[c].tcpstateflags != CLOSED && - uip_conns[c].lport == lastport) + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == lastport) { goto again; - } - - - for(c = 0; c < UIP_CONNS; ++c) { - if(uip_conns[c].tcpstateflags == CLOSED) - goto found_unused; - } - for(c = 0; c < UIP_CONNS; ++c) { - if(uip_conns[c].tcpstateflags == TIME_WAIT) - goto found_unused; - } - return (void *)0; - - found_unused: - - conn = &uip_conns[c]; - - conn->tcpstateflags = SYN_SENT | UIP_OUTSTANDING; - - conn->snd_nxt[0] = conn->ack_nxt[0] = iss[0]; - conn->snd_nxt[1] = conn->ack_nxt[1] = iss[1]; - conn->snd_nxt[2] = conn->ack_nxt[2] = iss[2]; - conn->snd_nxt[3] = conn->ack_nxt[3] = iss[3]; - - if(++conn->ack_nxt[3] == 0) { - if(++conn->ack_nxt[2] == 0) { - if(++conn->ack_nxt[1] == 0) { - ++conn->ack_nxt[0]; - } } } + + + conn = 0; + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == 0) { + conn = &uip_udp_conns[c]; + break; + } + } + + if(conn == 0) { + return 0; + } - conn->nrtx = 0; - conn->timer = 1; /* Send the SYN next time around. */ - conn->lport = htons(lastport); - conn->rport = htons(rport); + conn->lport = HTONS(lastport); + conn->rport = HTONS(rport); conn->ripaddr[0] = ripaddr[0]; conn->ripaddr[1] = ripaddr[1]; return conn; } -#endif /* UIP_ACTIVE_OPEN */ +#endif /* UIP_UDP */ +/*-----------------------------------------------------------------------------------*/ +void +uip_unlisten(u16_t port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(uip_listenports[c] == port) { + uip_listenports[c] = 0; + return; + } + } +} /*-----------------------------------------------------------------------------------*/ void uip_listen(u16_t port) { for(c = 0; c < UIP_LISTENPORTS; ++c) { if(uip_listenports[c] == 0) { - uip_listenports[c] = htons(port); - break; + uip_listenports[c] = port; + return; } } } /*-----------------------------------------------------------------------------------*/ +/* XXX: IP fragment reassembly: not well-tested. */ + +#if UIP_REASSEMBLY +#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) +static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; +static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; +static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, + 0x0f, 0x07, 0x03, 0x01}; +static u16_t uip_reasslen; +static u8_t uip_reassflags; +#define UIP_REASS_FLAG_LASTFRAG 0x01 +static u8_t uip_reasstmr; + +#define IP_HLEN 20 +#define IP_MF 0x20 + +static u8_t +uip_reass(void) +{ + u16_t offset, len; + u16_t i; + + /* If ip_reasstmr is zero, no packet is present in the buffer, so we + write the IP header of the fragment into the reassembly + buffer. The timer is updated with the maximum age. */ + if(uip_reasstmr == 0) { + memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN); + uip_reasstmr = UIP_REASS_MAXAGE; + uip_reassflags = 0; + /* Clear the bitmap. */ + memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); + } + + /* Check if the incoming fragment matches the one currently present + in the reasembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && + BUF->srcipaddr[1] == FBUF->srcipaddr[1] && + BUF->destipaddr[0] == FBUF->destipaddr[0] && + BUF->destipaddr[1] == FBUF->destipaddr[1] && + BUF->ipid[0] == FBUF->ipid[0] && + BUF->ipid[1] == FBUF->ipid[1]) { + + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; + + /* If the offset or the offset + fragment length overflows the + reassembly buffer, we discard the entire packet. */ + if(offset > UIP_REASS_BUFSIZE || + offset + len > UIP_REASS_BUFSIZE) { + uip_reasstmr = 0; + goto nullreturn; + } + + /* Copy the fragment into the reassembly buffer, at the right + offset. */ + memcpy(&uip_reassbuf[IP_HLEN + offset], + (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), + len); + + /* Update the bitmap. */ + if(offset / (8 * 8) == (offset + len) / (8 * 8)) { + /* If the two endpoints are in the same byte, we only update + that byte. */ + + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7] & + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } else { + /* If the two endpoints are in different bytes, we update the + bytes in the endpoints and fill the stuff inbetween with + 0xff. */ + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7]; + for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { + uip_reassbitmap[i] = 0xff; + } + uip_reassbitmap[(offset + len) / (8 * 8)] |= + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } + + /* If this fragment has the More Fragments flag set to zero, we + know that this is the last fragment, so we can calculate the + size of the entire packet. We also set the + IP_REASS_FLAG_LASTFRAG flag to indicate that we have received + the final fragment. */ + + if((BUF->ipoffset[0] & IP_MF) == 0) { + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; + uip_reasslen = offset + len; + } + + /* Finally, we check if we have a full packet in the buffer. We do + this by checking if we have the last fragment and if all bits + in the bitmap are set. */ + if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { + /* Check all bytes up to and including all but the last byte in + the bitmap. */ + for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { + if(uip_reassbitmap[i] != 0xff) { + goto nullreturn; + } + } + /* Check the last byte in the bitmap. It should contain just the + right amount of bits. */ + if(uip_reassbitmap[uip_reasslen / (8 * 8)] != + (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { + goto nullreturn; + } + + /* If we have come this far, we have a full packet in the + buffer, so we allocate a pbuf and copy the packet into it. We + also reset the timer. */ + uip_reasstmr = 0; + memcpy(BUF, FBUF, uip_reasslen); + + /* Pretend to be a "normal" (i.e., not fragmented) IP packet + from now on. */ + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + BUF->len[0] = uip_reasslen >> 8; + BUF->len[1] = uip_reasslen & 0xff; + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + + return uip_reasslen; + } + } + + nullreturn: + return 0; +} +#endif /* UIP_REASSEMBL */ +/*-----------------------------------------------------------------------------------*/ +static void +uip_add_rcv_nxt(u16_t n) +{ + uip_add32(uip_conn->rcv_nxt, n); + uip_conn->rcv_nxt[0] = uip_acc32[0]; + uip_conn->rcv_nxt[1] = uip_acc32[1]; + uip_conn->rcv_nxt[2] = uip_acc32[2]; + uip_conn->rcv_nxt[3] = uip_acc32[3]; +} +/*-----------------------------------------------------------------------------------*/ void uip_process(u8_t flag) { + register struct uip_conn *uip_connr = uip_conn; + uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; - + + /* Check if we were invoked because of the perodic timer fireing. */ if(flag == UIP_TIMER) { +#if UIP_REASSEMBLY + if(uip_reasstmr != 0) { + --uip_reasstmr; + } +#endif /* UIP_REASSEMBLY */ /* Increase the initial sequence number. */ if(++iss[3] == 0) { if(++iss[2] == 0) { @@ -256,22 +500,23 @@ uip_process(u8_t flag) } } uip_len = 0; - if(uip_conn->tcpstateflags == TIME_WAIT || - uip_conn->tcpstateflags == FIN_WAIT_2) { - ++(uip_conn->timer); - if(uip_conn->timer == UIP_TIME_WAIT_TIMEOUT) { - uip_conn->tcpstateflags = CLOSED; + if(uip_connr->tcpstateflags == TIME_WAIT || + uip_connr->tcpstateflags == FIN_WAIT_2) { + ++(uip_connr->timer); + if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { + uip_connr->tcpstateflags = CLOSED; } - } else if(uip_conn->tcpstateflags != CLOSED) { + } else if(uip_connr->tcpstateflags != CLOSED) { /* If the connection has outstanding data, we increase the connection's timer and see if it has reached the RTO value in which case we retransmit. */ - if(uip_conn->tcpstateflags & UIP_OUTSTANDING) { - --(uip_conn->timer); - if(uip_conn->timer == 0) { - - if(uip_conn->nrtx == UIP_MAXRTX) { - uip_conn->tcpstateflags = CLOSED; + if(uip_outstanding(uip_connr)) { + if(uip_connr->timer-- == 0) { + if(uip_connr->nrtx == UIP_MAXRTX || + ((uip_connr->tcpstateflags == SYN_SENT || + uip_connr->tcpstateflags == SYN_RCVD) && + uip_connr->nrtx == UIP_MAXSYNRTX)) { + uip_connr->tcpstateflags = CLOSED; /* We call UIP_APPCALL() with uip_flags set to UIP_TIMEDOUT to inform the application that the @@ -285,9 +530,10 @@ uip_process(u8_t flag) } /* Exponential backoff. */ - uip_conn->timer = UIP_RTO << (uip_conn->nrtx > 4? 4: uip_conn->nrtx); - - ++(uip_conn->nrtx); + uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? + 4: + uip_connr->nrtx); + ++(uip_connr->nrtx); /* Ok, so we need to retransmit. We do this differently depending on which state we are in. In ESTABLISHED, we @@ -296,7 +542,7 @@ uip_process(u8_t flag) SYNACK that we sent earlier and in LAST_ACK we have to retransmit our FINACK. */ UIP_STAT(++uip_stat.tcp.rexmit); - switch(uip_conn->tcpstateflags & TS_MASK) { + switch(uip_connr->tcpstateflags & TS_MASK) { case SYN_RCVD: /* In the SYN_RCVD state, we should retransmit our SYNACK. */ @@ -315,6 +561,7 @@ uip_process(u8_t flag) the code for sending out the packet (the apprexmit label). */ uip_len = 0; + uip_slen = 0; uip_flags = UIP_REXMIT; UIP_APPCALL(); goto apprexmit; @@ -327,20 +574,37 @@ uip_process(u8_t flag) } } - } else if((uip_conn->tcpstateflags & TS_MASK) == ESTABLISHED) { + } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { /* If there was no need for a retransmission, we poll the application for new data. */ uip_len = 0; + uip_slen = 0; uip_flags = UIP_POLL; UIP_APPCALL(); goto appsend; } - } + } goto drop; } +#if UIP_UDP + if(flag == UIP_UDP_TIMER) { + if(uip_udp_conn->lport != 0) { + uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; + uip_len = uip_slen = 0; + uip_flags = UIP_POLL; + UIP_UDP_APPCALL(); + goto udp_send; + } else { + goto drop; + } + } +#endif /* This is where the input processing starts. */ UIP_STAT(++uip_stat.ip.recv); + + + /* Start of IPv4 input header processing code. */ /* Check validity of the IP header. */ if(BUF->vhl != 0x45) { /* IP version and header length. */ @@ -354,50 +618,51 @@ uip_process(u8_t flag) uip_len doesn't match the size reported in the IP header, there has been a transmission error and we drop the packet. */ -#if UIP_BUFSIZE > 255 - if(BUF->len[0] != (uip_len >> 8)) { - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.hblenerr); - UIP_LOG("ip: invalid length, high byte."); - /* IP length, high byte. */ - goto drop; + if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ + uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); } - if(BUF->len[1] != (uip_len & 0xff)) { - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.lblenerr); - UIP_LOG("ip: invalid length, low byte."); - /* IP length, low byte. */ - goto drop; + if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ + uip_len = (uip_len & 0xff00) | BUF->len[1]; } -#else - if(BUF->len[0] != 0) { /* IP length, high byte. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.hblenerr); - UIP_LOG("ip: invalid length, high byte."); - goto drop; - } - if(BUF->len[1] != uip_len) { /* IP length, low byte. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.lblenerr); - UIP_LOG("ip: invalid length, low byte."); - goto drop; - } -#endif /* UIP_BUFSIZE > 255 */ - if(BUF->ipoffset[0] & 0x3f) { /* We don't allow IP fragments. */ + /* Check the fragment flag. */ + if((BUF->ipoffset[0] & 0x3f) != 0 || + BUF->ipoffset[1] != 0) { +#if UIP_REASSEMBLY + uip_len = uip_reass(); + if(uip_len == 0) { + goto drop; + } +#else UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.fragerr); UIP_LOG("ip: fragment dropped."); goto drop; +#endif /* UIP_REASSEMBLY */ } - /* Check if the packet is destined for our IP address. */ - if(BUF->destipaddr[0] != htons(((u16_t)UIP_IPADDR0 << 8) | UIP_IPADDR1)) { + /* If we are configured to use ping IP address configuration and + hasn't been assigned an IP address yet, we accept all ICMP + packets. */ +#if UIP_PINGADDRCONF + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { + if(BUF->proto == UIP_PROTO_ICMP) { + UIP_LOG("ip: possible ping config packet received."); + goto icmp_input; + } else { + UIP_LOG("ip: packet dropped since no address assigned."); + goto drop; + } + } +#endif /* UIP_PINGADDRCONF */ + + /* Check if the packet is destined for our IP address. */ + if(BUF->destipaddr[0] != uip_hostaddr[0]) { UIP_STAT(++uip_stat.ip.drop); UIP_LOG("ip: packet not for us."); goto drop; } - if(BUF->destipaddr[1] != htons(((u16_t)UIP_IPADDR2 << 8) | UIP_IPADDR3)) { + if(BUF->destipaddr[1] != uip_hostaddr[1]) { UIP_STAT(++uip_stat.ip.drop); UIP_LOG("ip: packet not for us."); goto drop; @@ -411,18 +676,24 @@ uip_process(u8_t flag) goto drop; } - if(BUF->proto == IP_PROTO_TCP) /* Check for TCP packet. If so, jump + if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump to the tcp_input label. */ goto tcp_input; - if(BUF->proto != IP_PROTO_ICMP) { /* We only allow ICMP packets from - here. */ +#if UIP_UDP + if(BUF->proto == UIP_PROTO_UDP) + goto udp_input; +#endif /* UIP_UDP */ + + if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from + here. */ UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.protoerr); UIP_LOG("ip: neither tcp nor icmp."); goto drop; } - + + icmp_input: UIP_STAT(++uip_stat.icmp.recv); /* ICMP echo (i.e., ping) processing. This is simple, we only change @@ -435,29 +706,114 @@ uip_process(u8_t flag) goto drop; } + /* If we are configured to use ping IP address assignment, we use + the destination IP address of this ping packet and assign it to + ourself. */ +#if UIP_PINGADDRCONF + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { + uip_hostaddr[0] = BUF->destipaddr[0]; + uip_hostaddr[1] = BUF->destipaddr[1]; + } +#endif /* UIP_PINGADDRCONF */ + ICMPBUF->type = ICMP_ECHO_REPLY; - if(ICMPBUF->icmpchksum >= htons(0xffff - (ICMP_ECHO << 8))) { - ICMPBUF->icmpchksum += htons(ICMP_ECHO << 8) + 1; + if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; } else { - ICMPBUF->icmpchksum += htons(ICMP_ECHO << 8); + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); } /* Swap IP addresses. */ - tmpport = BUF->destipaddr[0]; + tmp16 = BUF->destipaddr[0]; BUF->destipaddr[0] = BUF->srcipaddr[0]; - BUF->srcipaddr[0] = tmpport; - tmpport = BUF->destipaddr[1]; + BUF->srcipaddr[0] = tmp16; + tmp16 = BUF->destipaddr[1]; BUF->destipaddr[1] = BUF->srcipaddr[1]; - BUF->srcipaddr[1] = tmpport; + BUF->srcipaddr[1] = tmp16; UIP_STAT(++uip_stat.icmp.sent); goto send; + /* End of IPv4 input header processing code. */ + + +#if UIP_UDP + /* UDP input processing. */ + udp_input: + /* UDP processing is really just a hack. We don't do anything to the + UDP/IP headers, but let the UDP application do all the hard + work. If the application sets uip_slen, it has a packet to + send. */ +#if UIP_UDP_CHECKSUMS + if(uip_udpchksum() != 0xffff) { + UIP_STAT(++uip_stat.udp.drop); + UIP_STAT(++uip_stat.udp.chkerr); + UIP_LOG("udp: bad checksum."); + goto drop; + } +#endif /* UIP_UDP_CHECKSUMS */ + + /* Demultiplex this UDP packet between the UDP "connections". */ + for(uip_udp_conn = &uip_udp_conns[0]; + uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; + ++uip_udp_conn) { + if(uip_udp_conn->lport != 0 && + UDPBUF->destport == uip_udp_conn->lport && + (uip_udp_conn->rport == 0 || + UDPBUF->srcport == uip_udp_conn->rport) && + BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && + BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { + goto udp_found; + } + } + goto drop; + + udp_found: + uip_len = uip_len - 28; + uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; + uip_flags = UIP_NEWDATA; + uip_slen = 0; + UIP_UDP_APPCALL(); + udp_send: + if(uip_slen == 0) { + goto drop; + } + uip_len = uip_slen + 28; + + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); + + BUF->proto = UIP_PROTO_UDP; + + UDPBUF->udplen = HTONS(uip_slen + 8); + UDPBUF->udpchksum = 0; +#if UIP_UDP_CHECKSUMS + /* Calculate UDP checksum. */ + UDPBUF->udpchksum = ~(uip_udpchksum()); + if(UDPBUF->udpchksum == 0) { + UDPBUF->udpchksum = 0xffff; + } +#endif /* UIP_UDP_CHECKSUMS */ + + BUF->srcport = uip_udp_conn->lport; + BUF->destport = uip_udp_conn->rport; + + BUF->srcipaddr[0] = uip_hostaddr[0]; + BUF->srcipaddr[1] = uip_hostaddr[1]; + BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; + BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; + + uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; + goto ip_send_nolen; +#endif /* UIP_UDP */ + /* TCP input processing. */ tcp_input: UIP_STAT(++uip_stat.tcp.recv); - + + /* Start of TCP input header processing code. */ + if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP checksum. */ UIP_STAT(++uip_stat.tcp.drop); @@ -468,26 +824,27 @@ uip_process(u8_t flag) /* Demultiplex this segment. */ /* First check any active connections. */ - for(uip_conn = &uip_conns[0]; uip_conn < &uip_conns[UIP_CONNS]; ++uip_conn) { - if(uip_conn->tcpstateflags != CLOSED && - BUF->srcipaddr[0] == uip_conn->ripaddr[0] && - BUF->srcipaddr[1] == uip_conn->ripaddr[1] && - BUF->destport == uip_conn->lport && - BUF->srcport == uip_conn->rport) + for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) { + if(uip_connr->tcpstateflags != CLOSED && + BUF->destport == uip_connr->lport && + BUF->srcport == uip_connr->rport && + BUF->srcipaddr[0] == uip_connr->ripaddr[0] && + BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { goto found; + } } /* If we didn't find and active connection that expected the packet, either this packet is an old duplicate, or this is a SYN packet destined for a connection in LISTEN. If the SYN flag isn't set, it is an old packet and we send a RST. */ - if(BUF->flags != TCP_SYN) + if((BUF->flags & TCP_CTL) != TCP_SYN) goto reset; - tmpport = BUF->destport; + tmp16 = BUF->destport; /* Next, check listening connections. */ - for(c = 0; c < UIP_LISTENPORTS && uip_listenports[c] != 0; ++c) { - if(tmpport == uip_listenports[c]) + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(tmp16 == uip_listenports[c]) goto found_listen; } @@ -534,18 +891,19 @@ uip_process(u8_t flag) } /* Swap port numbers. */ - tmpport = BUF->srcport; + tmp16 = BUF->srcport; BUF->srcport = BUF->destport; - BUF->destport = tmpport; + BUF->destport = tmp16; /* Swap IP addresses. */ - tmpport = BUF->destipaddr[0]; + tmp16 = BUF->destipaddr[0]; BUF->destipaddr[0] = BUF->srcipaddr[0]; - BUF->srcipaddr[0] = tmpport; - tmpport = BUF->destipaddr[1]; + BUF->srcipaddr[0] = tmp16; + tmp16 = BUF->destipaddr[1]; BUF->destipaddr[1] = BUF->srcipaddr[1]; - BUF->srcipaddr[1] = tmpport; + BUF->srcipaddr[1] = tmp16; + /* And send out the RST packet! */ goto tcp_send_noconn; @@ -555,54 +913,62 @@ uip_process(u8_t flag) found_listen: /* First we check if there are any connections avaliable. Unused connections are kept in the same table as used connections, but - unused ones have the tcpstate set to CLOSED. */ + unused ones have the tcpstate set to CLOSED. Also, connections in + TIME_WAIT are kept track of and we'll use the oldest one if no + CLOSED connections are found. Thanks to Eddie C. Dost for a very + nice algorithm for the TIME_WAIT search. */ + uip_connr = 0; for(c = 0; c < UIP_CONNS; ++c) { - if(uip_conns[c].tcpstateflags == CLOSED) - goto found_unused_connection; + if(uip_conns[c].tcpstateflags == CLOSED) { + uip_connr = &uip_conns[c]; + break; + } + if(uip_conns[c].tcpstateflags == TIME_WAIT) { + if(uip_connr == 0 || + uip_conns[c].timer > uip_connr->timer) { + uip_connr = &uip_conns[c]; + } + } } - for(c = 0; c < UIP_CONNS; ++c) { - if(uip_conns[c].tcpstateflags == TIME_WAIT) - goto found_unused_connection; + + if(uip_connr == 0) { + /* All connections are used already, we drop packet and hope that + the remote end will retransmit the packet at a time when we + have more spare connections. */ + UIP_STAT(++uip_stat.tcp.syndrop); + UIP_LOG("tcp: found no unused connections."); + goto drop; } - /* All connections are used already, we drop packet and hope that - the remote end will retransmit the packet at a time when we have - more spare connections. */ - UIP_STAT(++uip_stat.tcp.syndrop); - UIP_LOG("tcp: found no unused connections."); - goto drop; - - /* This label will be jumped to if we have found an unused - connection that we can use. */ - found_unused_connection: - uip_conn = &uip_conns[c]; - + uip_conn = uip_connr; + /* Fill in the necessary fields for the new connection. */ - uip_conn->timer = UIP_RTO; - uip_conn->nrtx = 0; - uip_conn->lport = BUF->destport; - uip_conn->rport = BUF->srcport; - uip_conn->ripaddr[0] = BUF->srcipaddr[0]; - uip_conn->ripaddr[1] = BUF->srcipaddr[1]; - uip_conn->tcpstateflags = SYN_RCVD | UIP_OUTSTANDING; + uip_connr->rto = uip_connr->timer = UIP_RTO; + uip_connr->sa = 0; + uip_connr->sv = 4; + uip_connr->nrtx = 0; + uip_connr->lport = BUF->destport; + uip_connr->rport = BUF->srcport; + uip_connr->ripaddr[0] = BUF->srcipaddr[0]; + uip_connr->ripaddr[1] = BUF->srcipaddr[1]; + uip_connr->tcpstateflags = SYN_RCVD; - uip_conn->snd_nxt[0] = uip_conn->ack_nxt[0] = iss[0]; - uip_conn->snd_nxt[1] = uip_conn->ack_nxt[1] = iss[1]; - uip_conn->snd_nxt[2] = uip_conn->ack_nxt[2] = iss[2]; - uip_conn->snd_nxt[3] = uip_conn->ack_nxt[3] = iss[3]; - uip_add_ack_nxt(1); + uip_connr->snd_nxt[0] = iss[0]; + uip_connr->snd_nxt[1] = iss[1]; + uip_connr->snd_nxt[2] = iss[2]; + uip_connr->snd_nxt[3] = iss[3]; + uip_connr->len = 1; /* rcv_nxt should be the seqno from the incoming packet + 1. */ - uip_conn->rcv_nxt[3] = BUF->seqno[3]; - uip_conn->rcv_nxt[2] = BUF->seqno[2]; - uip_conn->rcv_nxt[1] = BUF->seqno[1]; - uip_conn->rcv_nxt[0] = BUF->seqno[0]; + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; uip_add_rcv_nxt(1); - /* Parse the TCP MSS option, if present. */ if((BUF->tcpoffset & 0xf0) > 0x50) { for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { - opt = uip_buf[40 + UIP_LLH_LEN + c]; + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; if(opt == 0x00) { /* End of options. */ break; @@ -610,18 +976,24 @@ uip_process(u8_t flag) ++c; /* NOP option. */ } else if(opt == 0x02 && - uip_buf[40 + UIP_LLH_LEN + c + 1] == 0x04) { + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { /* An MSS option with the right option length. */ - tmpport = (uip_buf[40 + UIP_LLH_LEN + c + 2] << 8) | - uip_buf[40 + UIP_LLH_LEN + c + 3]; - uip_conn->mss = tmpport > UIP_TCP_MSS? UIP_TCP_MSS: tmpport; + tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + (u16_t)uip_buf[40 + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = uip_connr->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; /* And we are done processing options. */ break; } else { /* All other options have a length field, so that we easily can skip past them. */ - c += uip_buf[40 + UIP_LLH_LEN + c + 1]; + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; } } } @@ -650,6 +1022,7 @@ uip_process(u8_t flag) /* This label will be jumped to if we found an active connection. */ found: + uip_conn = uip_connr; uip_flags = 0; /* We do a very naive form of TCP reset processing; we just accept @@ -657,21 +1030,12 @@ uip_process(u8_t flag) sequence number of this reset is wihtin our advertised window before we accept the reset. */ if(BUF->flags & TCP_RST) { - uip_conn->tcpstateflags = CLOSED; + uip_connr->tcpstateflags = CLOSED; UIP_LOG("tcp: got reset, aborting connection."); uip_flags = UIP_ABORT; UIP_APPCALL(); goto drop; - } - /* All segments that are come thus far should have the ACK flag set, - otherwise we drop the packet. */ - if(!(BUF->flags & TCP_ACK)) { - UIP_STAT(++uip_stat.tcp.drop); - UIP_STAT(++uip_stat.tcp.ackerr); - UIP_LOG("tcp: dropped non-ack segment."); - goto drop; - } - + } /* Calculated the length of the data, if the application has sent any data to us. */ c = (BUF->tcpoffset >> 4) << 2; @@ -684,32 +1048,55 @@ uip_process(u8_t flag) what we're expecting next. If not, we send out an ACK with the correct numbers in. */ if(uip_len > 0 && - (BUF->seqno[0] != uip_conn->rcv_nxt[0] || - BUF->seqno[1] != uip_conn->rcv_nxt[1] || - BUF->seqno[2] != uip_conn->rcv_nxt[2] || - BUF->seqno[3] != uip_conn->rcv_nxt[3])) { + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || + BUF->seqno[1] != uip_connr->rcv_nxt[1] || + BUF->seqno[2] != uip_connr->rcv_nxt[2] || + BUF->seqno[3] != uip_connr->rcv_nxt[3])) { goto tcp_send_ack; } /* Next, check if the incoming segment acknowledges any outstanding - data. If so, we also reset the retransmission timer. */ - if(BUF->ackno[0] == uip_conn->ack_nxt[0] && - BUF->ackno[1] == uip_conn->ack_nxt[1] && - BUF->ackno[2] == uip_conn->ack_nxt[2] && - BUF->ackno[3] == uip_conn->ack_nxt[3]) { - uip_conn->snd_nxt[0] = uip_conn->ack_nxt[0]; - uip_conn->snd_nxt[1] = uip_conn->ack_nxt[1]; - uip_conn->snd_nxt[2] = uip_conn->ack_nxt[2]; - uip_conn->snd_nxt[3] = uip_conn->ack_nxt[3]; - if(uip_conn->tcpstateflags & UIP_OUTSTANDING) { + data. If so, we update the sequence number, reset the length of + the outstanding data, calculate RTT estimations, and reset the + retransmission timer. */ + if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { + uip_add32(uip_connr->snd_nxt, uip_connr->len); + if(BUF->ackno[0] == uip_acc32[0] && + BUF->ackno[1] == uip_acc32[1] && + BUF->ackno[2] == uip_acc32[2] && + BUF->ackno[3] == uip_acc32[3]) { + /* Update sequence number. */ + uip_connr->snd_nxt[0] = uip_acc32[0]; + uip_connr->snd_nxt[1] = uip_acc32[1]; + uip_connr->snd_nxt[2] = uip_acc32[2]; + uip_connr->snd_nxt[3] = uip_acc32[3]; + + + /* Do RTT estimation, unless we have done retransmissions. */ + if(uip_connr->nrtx == 0) { + signed char m; + m = uip_connr->rto - uip_connr->timer; + /* This is taken directly from VJs original code in his paper */ + m = m - (uip_connr->sa >> 3); + uip_connr->sa += m; + if(m < 0) { + m = -m; + } + m = m - (uip_connr->sv >> 2); + uip_connr->sv += m; + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; + + } + /* Set the acknowledged flag. */ uip_flags = UIP_ACKDATA; - uip_conn->tcpstateflags &= ~UIP_OUTSTANDING; - uip_conn->timer = UIP_RTO; + /* Reset the retransmission timer. */ + uip_connr->timer = uip_connr->rto; } + } /* Do different things depending on in what state the connection is. */ - switch(uip_conn->tcpstateflags & TS_MASK) { + switch(uip_connr->tcpstateflags & TS_MASK) { /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not implemented, since we force the application to close when the peer sends a FIN (hence the application goes directly from @@ -720,9 +1107,14 @@ uip_process(u8_t flag) out the last time. Therefore, we want to have the UIP_ACKDATA flag set. If so, we enter the ESTABLISHED state. */ if(uip_flags & UIP_ACKDATA) { - uip_conn->tcpstateflags = ESTABLISHED; + uip_connr->tcpstateflags = ESTABLISHED; uip_flags = UIP_CONNECTED; - uip_len = 0; + uip_connr->len = 0; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + uip_slen = 0; UIP_APPCALL(); goto appsend; } @@ -747,34 +1139,41 @@ uip_process(u8_t flag) ++c; /* NOP option. */ } else if(opt == 0x02 && - uip_buf[40 + UIP_LLH_LEN + c + 1] == 0x04) { + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { /* An MSS option with the right option length. */ - tmpport = (uip_buf[40 + UIP_LLH_LEN + c + 2] << 8) | - uip_buf[40 + UIP_LLH_LEN + c + 3]; - uip_conn->mss = tmpport > UIP_TCP_MSS? UIP_TCP_MSS: tmpport; + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = + uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; /* And we are done processing options. */ break; } else { /* All other options have a length field, so that we easily can skip past them. */ - c += uip_buf[40 + UIP_LLH_LEN + c + 1]; + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; } } - } - - uip_conn->tcpstateflags = ESTABLISHED; - uip_conn->rcv_nxt[0] = BUF->seqno[0]; - uip_conn->rcv_nxt[1] = BUF->seqno[1]; - uip_conn->rcv_nxt[2] = BUF->seqno[2]; - uip_conn->rcv_nxt[3] = BUF->seqno[3]; + } + uip_connr->tcpstateflags = ESTABLISHED; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[3] = BUF->seqno[3]; uip_add_rcv_nxt(1); uip_flags = UIP_CONNECTED | UIP_NEWDATA; + uip_connr->len = 0; uip_len = 0; + uip_slen = 0; UIP_APPCALL(); goto appsend; } - goto drop; + goto reset; #endif /* UIP_ACTIVE_OPEN */ case ESTABLISHED: @@ -786,33 +1185,76 @@ uip_process(u8_t flag) If the incoming packet is a FIN, we should close the connection on this side as well, and we send out a FIN and enter the LAST_ACK - state. We require that the FIN will have to acknowledge all - outstanding data, otherwise we drop it. */ + state. We require that there is no outstanding data; otherwise the + sequence numbers will be screwed up. */ if(BUF->flags & TCP_FIN) { - uip_add_rcv_nxt(1 + uip_len); + if(uip_outstanding(uip_connr)) { + goto drop; + } + uip_add_rcv_nxt(1 + uip_len); uip_flags = UIP_CLOSE; - uip_len = 0; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + } UIP_APPCALL(); - uip_add_ack_nxt(1); - uip_conn->tcpstateflags = LAST_ACK | UIP_OUTSTANDING; - uip_conn->nrtx = 0; + uip_connr->len = 1; + uip_connr->tcpstateflags = LAST_ACK; + uip_connr->nrtx = 0; tcp_send_finack: BUF->flags = TCP_FIN | TCP_ACK; goto tcp_send_nodata; } + /* Check the URG flag. If this is set, the segment carries urgent + data that we must pass to the application. */ + if(BUF->flags & TCP_URG) { +#if UIP_URGDATA > 0 + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; + if(uip_urglen > uip_len) { + /* There is more urgent data in the next segment to come. */ + uip_urglen = uip_len; + } + uip_add_rcv_nxt(uip_urglen); + uip_len -= uip_urglen; + uip_urgdata = uip_appdata; + uip_appdata += uip_urglen; + } else { + uip_urglen = 0; +#endif /* UIP_URGDATA > 0 */ + uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; + uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; + } + /* If uip_len > 0 we have TCP data in the packet, and we flag this by setting the UIP_NEWDATA flag and update the sequence number we acknowledge. If the application has stopped the dataflow using uip_stop(), we must not accept any data packets from the remote host. */ - if(uip_len > 0 && !(uip_conn->tcpstateflags & UIP_STOPPED)) { + if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { uip_flags |= UIP_NEWDATA; uip_add_rcv_nxt(uip_len); } - + + /* Check if the available buffer space advertised by the other end + is smaller than the initial MSS for this connection. If so, we + set the current MSS to the window size to ensure that the + application does not send more data than the other end can + handle. + + If the remote host advertises a zero window, we set the MSS to + the initial MSS so that the application will send an entire MSS + of data. This data will not be acknowledged by the receiver, + and the application will retransmit it. This is called the + "persistent timer" and uses the retransmission mechanim. + */ + tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1]; + if(tmp16 > uip_connr->initialmss || + tmp16 == 0) { + tmp16 = uip_connr->initialmss; + } + uip_connr->mss = tmp16; /* If this packet constitutes an ACK for outstanding data (flagged by the UIP_ACKDATA flag, we should call the application since it @@ -831,53 +1273,91 @@ uip_process(u8_t flag) put into uip_len. If the application don't have any data to send, uip_len must be set to 0. */ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { + uip_slen = 0; UIP_APPCALL(); appsend: + if(uip_flags & UIP_ABORT) { - uip_conn->tcpstateflags = CLOSED; + uip_slen = 0; + uip_connr->tcpstateflags = CLOSED; BUF->flags = TCP_RST | TCP_ACK; goto tcp_send_nodata; } if(uip_flags & UIP_CLOSE) { - uip_add_ack_nxt(1); - uip_conn->tcpstateflags = FIN_WAIT_1 | UIP_OUTSTANDING; - uip_conn->nrtx = 0; + uip_slen = 0; + uip_connr->len = 1; + uip_connr->tcpstateflags = FIN_WAIT_1; + uip_connr->nrtx = 0; BUF->flags = TCP_FIN | TCP_ACK; goto tcp_send_nodata; } - /* If uip_len > 0, the application has data to be sent, in which - case we set the UIP_OUTSTANDING flag in the connection - structure. But we cannot send data if the application already - has outstanding data. */ - if(uip_len > 0 && - !(uip_conn->tcpstateflags & UIP_OUTSTANDING)) { - uip_conn->tcpstateflags |= UIP_OUTSTANDING; - uip_conn->nrtx = 0; - uip_add_ack_nxt(uip_len); + /* If uip_slen > 0, the application has data to be sent. */ + if(uip_slen > 0) { + + /* If the connection has acknowledged data, the contents of + the ->len variable should be discarded. */ + if((uip_flags & UIP_ACKDATA) != 0) { + uip_connr->len = 0; + } + + /* If the ->len variable is non-zero the connection has + already data in transit and cannot send anymore right + now. */ + if(uip_connr->len == 0) { + + /* The application cannot send more than what is allowed by + the mss (the minumum of the MSS and the available + window). */ + if(uip_slen > uip_connr->mss) { + uip_slen = uip_connr->mss; + } + + /* Remember how much data we send out now so that we know + when everything has been acknowledged. */ + uip_connr->len = uip_slen; + } else { + + /* If the application already had unacknowledged data, we + make sure that the application does not send (i.e., + retransmit) out more than it previously sent out. */ + uip_slen = uip_connr->len; + } } else { - uip_len = 0; + uip_connr->len = 0; } + uip_connr->nrtx = 0; apprexmit: + uip_appdata = uip_sappdata; + /* If the application has data to be sent, or if the incoming packet had new data in it, we must send out a packet. */ - if(uip_len > 0 || (uip_flags & UIP_NEWDATA)) { + if(uip_slen > 0 && uip_connr->len > 0) { /* Add the length of the IP and TCP headers. */ - uip_len = uip_len + 40; + uip_len = uip_connr->len + UIP_TCPIP_HLEN; /* We always set the ACK flag in response packets. */ - BUF->flags = TCP_ACK; + BUF->flags = TCP_ACK | TCP_PSH; /* Send the packet. */ goto tcp_send_noopts; } + /* If there is no data to send, just send out a pure ACK if + there is newdata. */ + if(uip_flags & UIP_NEWDATA) { + uip_len = UIP_TCPIP_HLEN; + BUF->flags = TCP_ACK; + goto tcp_send_noopts; + } } goto drop; case LAST_ACK: /* We can close this connection if the peer has acknowledged our FIN. This is indicated by the UIP_ACKDATA flag. */ if(uip_flags & UIP_ACKDATA) { - uip_conn->tcpstateflags = CLOSED; + uip_connr->tcpstateflags = CLOSED; + uip_flags = UIP_CLOSE; + UIP_APPCALL(); } break; @@ -890,15 +1370,19 @@ uip_process(u8_t flag) } if(BUF->flags & TCP_FIN) { if(uip_flags & UIP_ACKDATA) { - uip_conn->tcpstateflags = TIME_WAIT; - uip_conn->timer = 0; + uip_connr->tcpstateflags = TIME_WAIT; + uip_connr->timer = 0; + uip_connr->len = 0; } else { - uip_conn->tcpstateflags = CLOSING | UIP_OUTSTANDING; + uip_connr->tcpstateflags = CLOSING; } uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); goto tcp_send_ack; } else if(uip_flags & UIP_ACKDATA) { - uip_conn->tcpstateflags = FIN_WAIT_2; + uip_connr->tcpstateflags = FIN_WAIT_2; + uip_connr->len = 0; goto drop; } if(uip_len > 0) { @@ -911,9 +1395,11 @@ uip_process(u8_t flag) uip_add_rcv_nxt(uip_len); } if(BUF->flags & TCP_FIN) { - uip_conn->tcpstateflags = TIME_WAIT; - uip_conn->timer = 0; + uip_connr->tcpstateflags = TIME_WAIT; + uip_connr->timer = 0; uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); goto tcp_send_ack; } if(uip_len > 0) { @@ -926,8 +1412,8 @@ uip_process(u8_t flag) case CLOSING: if(uip_flags & UIP_ACKDATA) { - uip_conn->tcpstateflags = TIME_WAIT; - uip_conn->timer = 0; + uip_connr->tcpstateflags = TIME_WAIT; + uip_connr->timer = 0; } } goto drop; @@ -945,80 +1431,74 @@ uip_process(u8_t flag) /* We're done with the input processing. We are now ready to send a reply. Our job is to fill in all the fields of the TCP and IP headers before calculating the checksum and finally send the - packet. */ - BUF->ackno[0] = uip_conn->rcv_nxt[0]; - BUF->ackno[1] = uip_conn->rcv_nxt[1]; - BUF->ackno[2] = uip_conn->rcv_nxt[2]; - BUF->ackno[3] = uip_conn->rcv_nxt[3]; + packet. */ + BUF->ackno[0] = uip_connr->rcv_nxt[0]; + BUF->ackno[1] = uip_connr->rcv_nxt[1]; + BUF->ackno[2] = uip_connr->rcv_nxt[2]; + BUF->ackno[3] = uip_connr->rcv_nxt[3]; - BUF->seqno[0] = uip_conn->snd_nxt[0]; - BUF->seqno[1] = uip_conn->snd_nxt[1]; - BUF->seqno[2] = uip_conn->snd_nxt[2]; - BUF->seqno[3] = uip_conn->snd_nxt[3]; + BUF->seqno[0] = uip_connr->snd_nxt[0]; + BUF->seqno[1] = uip_connr->snd_nxt[1]; + BUF->seqno[2] = uip_connr->snd_nxt[2]; + BUF->seqno[3] = uip_connr->snd_nxt[3]; - BUF->srcport = uip_conn->lport; - BUF->destport = uip_conn->rport; + BUF->proto = UIP_PROTO_TCP; + + BUF->srcport = uip_connr->lport; + BUF->destport = uip_connr->rport; -#if BYTE_ORDER == BIG_ENDIAN - BUF->srcipaddr[0] = ((UIP_IPADDR0 << 8) | UIP_IPADDR1); - BUF->srcipaddr[1] = ((UIP_IPADDR2 << 8) | UIP_IPADDR3); -#else - BUF->srcipaddr[0] = ((UIP_IPADDR1 << 8) | UIP_IPADDR0); - BUF->srcipaddr[1] = ((UIP_IPADDR3 << 8) | UIP_IPADDR2); -#endif /* BYTE_ORDER == BIG_ENDIAN */ + BUF->srcipaddr[0] = uip_hostaddr[0]; + BUF->srcipaddr[1] = uip_hostaddr[1]; + BUF->destipaddr[0] = uip_connr->ripaddr[0]; + BUF->destipaddr[1] = uip_connr->ripaddr[1]; + - BUF->destipaddr[0] = uip_conn->ripaddr[0]; - BUF->destipaddr[1] = uip_conn->ripaddr[1]; - - if(uip_conn->tcpstateflags & UIP_STOPPED) { + if(uip_connr->tcpstateflags & UIP_STOPPED) { /* If the connection has issued uip_stop(), we advertise a zero window so that the remote host will stop sending data. */ BUF->wnd[0] = BUF->wnd[1] = 0; } else { -#if (UIP_TCP_MSS) > 255 - BUF->wnd[0] = (uip_conn->mss >> 8); -#else - BUF->wnd[0] = 0; -#endif /* UIP_MSS */ - BUF->wnd[1] = (uip_conn->mss & 0xff); + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); } - + tcp_send_noconn: + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); + + /* Calculate TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + + ip_send_nolen: + BUF->vhl = 0x45; BUF->tos = 0; BUF->ipoffset[0] = BUF->ipoffset[1] = 0; BUF->ttl = UIP_TTL; - BUF->proto = IP_PROTO_TCP; - -#if UIP_BUFSIZE > 255 - BUF->len[0] = (uip_len >> 8); - BUF->len[1] = (uip_len & 0xff); -#else - BUF->len[0] = 0; - BUF->len[1] = uip_len; -#endif /* UIP_BUFSIZE > 255 */ - ++ipid; BUF->ipid[0] = ipid >> 8; BUF->ipid[1] = ipid & 0xff; - /* Calculate IP and TCP checksums. */ + /* Calculate IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); - BUF->tcpchksum = 0; - BUF->tcpchksum = ~(uip_tcpchksum()); UIP_STAT(++uip_stat.tcp.sent); send: UIP_STAT(++uip_stat.ip.sent); - /* The data that should be sent is not present in the uip_buf, and - the length of the data is in the variable uip_len. It is not our - responsibility to do the actual sending of the data however. That - is taken care of by the wrapper code, and only if uip_len > 0. */ + /* Return and let the caller do the actual transmission. */ return; drop: uip_len = 0; return; } /*-----------------------------------------------------------------------------------*/ +u16_t +htons(u16_t val) +{ + return HTONS(val); +} +/*-----------------------------------------------------------------------------------*/ +/** @} */ diff --git a/uip/uip.h b/uip/uip.h index f10dc93..19e146b 100644 --- a/uip/uip.h +++ b/uip/uip.h @@ -1,5 +1,22 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \file + * Header file for the uIP TCP/IP stack. + * \author Adam Dunkels + * + * The uIP TCP/IP stack header file contains definitions for a number + * of C macros that are used by uIP programs as well as internal uIP + * structures, TCP/IP header structures and function declarations. + * + */ + + /* - * Copyright (c) 2001-2002, Adam Dunkels. + * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +27,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +45,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip.h,v 1.19 2002/01/15 17:54:54 adam Exp $ + * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ * */ @@ -46,92 +60,446 @@ * handled by the following three functions. */ -/* uip_init(): +/** + * \defgroup uipconffunc uIP configuration functions + * @{ * - * Must be called at boot up to configure the uIP data structures. + * The uIP configuration functions are used for setting run-time + * parameters in uIP such as IP addresses. + */ + +/** + * Set the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * \param addr A pointer to a 4-byte representation of the IP address. + * + * \hideinitializer + */ +#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ + uip_hostaddr[1] = addr[1]; } while(0) + +/** + * Get the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * \param addr A pointer to a 4-byte array that will be filled in with + * the currently configured IP address. + * + * \hideinitializer + */ +#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ + addr[1] = uip_hostaddr[1]; } while(0) + +/** @} */ + +/** + * \defgroup uipinit uIP initialization functions + * @{ + * + * The uIP initialization functions are used for booting uIP. + */ + +/** + * uIP initialization function. + * + * This function should be called at boot up to initilize the uIP + * TCP/IP stack. */ void uip_init(void); -/* uip_periodic(conn): +/** @} */ + +/** + * \defgroup uipdevfunc uIP device driver functions + * @{ * - * Should be called when the periodic timer has fired. Should be - * called once per connection (0 - UIP_CONNS). + * These functions are used by a network device driver for interacting + * with uIP. + */ + +/** + * Process an incoming packet. + * + * This function should be called when the device driver has received + * a packet from the network. The packet from the device driver must + * be present in the uip_buf buffer, and the length of the packet + * should be placed in the uip_len variable. + * + * When the function returns, there may be an outbound packet placed + * in the uip_buf packet buffer. If so, the uip_len variable is set to + * the length of the packet. If no packet is to be sent out, the + * uip_len variable is set to 0. + * + * The usual way of calling the function is presented by the source + * code below. + \code + uip_len = devicedriver_poll(); + if(uip_len > 0) { + uip_input(); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uIP ARP code before calling + * this function: + \code + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + uip_len = ethernet_devicedrver_poll(); + if(uip_len > 0) { + if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { + uip_arp_ipin(); + uip_input(); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(); + if(uip_len > 0) { + ethernet_devicedriver_send(); + } + } + \endcode + * + * \hideinitializer + */ +#define uip_input() uip_process(UIP_DATA) + +/** + * Periodic processing for a connection identified by its number. + * + * This function does the necessary periodic processing (timers, + * polling) for a uIP TCP conneciton, and should be called when the + * periodic uIP timer goes off. It should be called for every + * connection, regardless of whether they are open of closed. + * + * When the function returns, it may have an outbound packet waiting + * for service in the uIP packet buffer, and if so the uip_len + * variable is set to a value larger than zero. The device driver + * should be called to send out the packet. + * + * The ususal way of calling the function is through a for() loop like + * this: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uip_arp_out() function before + * calling the device driver: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the connection which is to be periodically polled. + * + * \hideinitializer */ #define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ uip_process(UIP_TIMER); } while (0) -/* uip_input(): +/** + * Periodic processing for a connection identified by a pointer to its structure. * - * Is called when the network device driver has received new data. + * Same as uip_periodic() but takes a pointer to the actual uip_conn + * struct instead of an integer as its argument. This function can be + * used to force periodic processing of a specific connection. + * + * \param conn A pointer to the uip_conn struct for the connection to + * be processed. + * + * \hideinitializer */ -#define uip_input() uip_process(UIP_DATA) +#define uip_periodic_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_TIMER); } while (0) + +#if UIP_UDP +/** + * Periodic processing for a UDP connection identified by its number. + * + * This function is essentially the same as uip_prerioic(), but for + * UDP connections. It is called in a similar fashion as the + * uip_periodic() function: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note As for the uip_periodic() function, special care has to be + * taken when using uIP together with ARP and Ethernet: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the UDP connection to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ + uip_process(UIP_UDP_TIMER); } while (0) + +/** + * Periodic processing for a UDP connection identified by a pointer to + * its structure. + * + * Same as uip_udp_periodic() but takes a pointer to the actual + * uip_conn struct instead of an integer as its argument. This + * function can be used to force periodic processing of a specific + * connection. + * + * \param conn A pointer to the uip_udp_conn struct for the connection + * to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ + uip_process(UIP_UDP_TIMER); } while (0) + + +#endif /* UIP_UDP */ + +/** + * The uIP packet buffer. + * + * The uip_buf array is used to hold incoming and outgoing + * packets. The device driver should place incoming data into this + * buffer. When sending data, the device driver should read the link + * level headers and the TCP/IP headers from this buffer. The size of + * the link level headers is configured by the UIP_LLH_LEN define. + * + * \note The application data need not be placed in this buffer, so + * the device driver must read it from the place pointed to by the + * uip_appdata pointer as illustrated by the following example: + \code + void + devicedriver_send(void) + { + hwsend(&uip_buf[0], UIP_LLH_LEN); + hwsend(&uip_buf[UIP_LLH_LEN], 40); + hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); + } + \endcode + */ +extern u8_t uip_buf[UIP_BUFSIZE+2]; + +/** @} */ /*-----------------------------------------------------------------------------------*/ /* Functions that are used by the uIP application program. Opening and * closing connections, sending and receiving data, etc. is all * handled by the functions below. */ - -/* uip_listen(port): +/** + * \defgroup uipappfunc uIP application functions + * @{ * - * Starts listening to the specified port. + * Functions used by an application running of top of uIP. + */ + +/** + * Start listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_listen(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. */ void uip_listen(u16_t port); -/* uip_connect(ripaddr, port): +/** + * Stop listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_unlisten(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. + */ +void uip_unlisten(u16_t port); + +/** + * Connect to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It allocates a new connection identifier, + * sets the connection to the SYN_SENT state and sets the + * retransmission timer to 0. This will cause a TCP SYN segment to be + * sent out the next time this connection is periodically processed, + * which usually is done within 0.5 seconds after the call to + * uip_connect(). + * + * \note This function is avaliable only if support for active open + * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. + * + * \note Since this function requires the port number to be in network + * byte order, a convertion using HTONS() or htons() is necessary. + * + \code + u16_t ipaddr[2]; + + uip_ipaddr(ipaddr, 192,168,1,2); + uip_connect(ipaddr, HTONS(80)); + \endcode + * + * \param ripaddr A pointer to a 4-byte array representing the IP + * address of the remote hot. + * + * \param port A 16-bit port number in network byte order. + * + * \return A pointer to the uIP connection identifier for the new connection, + * or NULL if no connection could be allocated. * - * Returns a connection identifier that connects to a port on the - * specified host (given in ripaddr). If no connections are avaliable, - * the function returns NULL. This function is avaliable only if - * support for active open has been configured (#define - * UIP_ACTIVE_OPEN 1 in uipopt.h) */ struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); -/* uip_send(data, len): - * - * Send data on the current connection. The length of the data must - * not exceed the maxium segment size (MSS) for the connection. - */ -#define uip_send(data, len) do { uip_appdata = data; uip_len = len;} while(0) -/* uip_datalen(): + +/** + * \internal * - * The length of the data that is currently avaliable (if avaliable) - * in the uip_appdata buffer. The test function uip_data() is - * used to check if data is avaliable. + * Check if a connection has outstanding (i.e., unacknowledged) data. + * + * \param conn A pointer to the uip_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_outstanding(conn) ((conn)->len) + +/** + * Send data on the current connection. + * + * This function is used to send out a single segment of TCP + * data. Only applications that have been invoked by uIP for event + * processing can send data. + * + * The amount of data that actually is sent out after a call to this + * funcion is determined by the maximum amount of data TCP allows. uIP + * will automatically crop the data so that only the appropriate + * amount of data is sent. The function uip_mss() can be used to query + * uIP for the amount of data that actually will be sent. + * + * \note This function does not guarantee that the sent data will + * arrive at the destination. If the data is lost in the network, the + * application will be invoked with the uip_rexmit() event being + * set. The application will then have to resend the data using this + * function. + * + * \param data A pointer to the data which is to be sent. + * + * \param len The maximum amount of data bytes to be sent. + * + * \hideinitializer + */ +#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) + +/** + * The length of any incoming data that is currently avaliable (if avaliable) + * in the uip_appdata buffer. + * + * The test function uip_data() must first be used to check if there + * is any data available at all. + * + * \hideinitializer */ #define uip_datalen() uip_len -/* uip_close(): +/** + * The length of any out-of-band data (urgent data) that has arrived + * on the connection. * + * \note The configuration parameter UIP_URGDATA must be set for this + * function to be enabled. + * + * \hideinitializer + */ +#define uip_urgdatalen() uip_urglen + +/** * Close the current connection. + * + * This function will close the current connection in a nice way. + * + * \hideinitializer */ #define uip_close() (uip_flags = UIP_CLOSE) -/* uip_abort(): - * +/** * Abort the current connection. + * + * This function will abort (reset) the current connection, and is + * usually used when an error has occured that prevents using the + * uip_close() function. + * + * \hideinitializer */ #define uip_abort() (uip_flags = UIP_ABORT) -/* uip_stop(): +/** + * Tell the sending host to stop sending data. * - * Close our receiver's window so that we stop receiving data for the - * current connection. + * This function will close our receiver's window so that we stop + * receiving data for the current connection. + * + * \hideinitializer */ #define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) -/* uip_stopped(): +/** + * Find out if the current connection has been previously stopped with + * uip_stop(). * - * Find out if the current connection has been previously stopped. + * \hideinitializer */ -#define uip_stopped() (uip_conn->tcpstateflags & UIP_STOPPED) +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) -/* uip_restart(): +/** + * Restart the current connection, if is has previously been stopped + * with uip_stop(). * - * Open the window again so that we start receiving data for the - * current connection. + * This function will open the receiver's window again so that we + * start receiving data for the current connection. + * + * \hideinitializer */ #define uip_restart() do { uip_flags |= UIP_NEWDATA; \ uip_conn->tcpstateflags &= ~UIP_STOPPED; \ @@ -141,128 +509,238 @@ struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); /* uIP tests that can be made to determine in what state the current connection is, and what the application function should do. */ -/* uip_newdata(): +/** + * Is new incoming data available? * * Will reduce to non-zero if there is new data for the application * present at the uip_appdata pointer. The size of the data is * avaliable through the uip_len variable. + * + * \hideinitializer */ #define uip_newdata() (uip_flags & UIP_NEWDATA) -/* uip_acked(): +/** + * Has previously sent data been acknowledged? * * Will reduce to non-zero if the previously sent data has been * acknowledged by the remote host. This means that the application - * can send new data. uip_reset_acked() can be used to reset the acked - * flag. + * can send new data. + * + * \hideinitializer */ #define uip_acked() (uip_flags & UIP_ACKDATA) -#define uip_reset_acked() (uip_flags &= ~UIP_ACKDATA) -/* uip_connected(): +/** + * Has the connection just been connected? * * Reduces to non-zero if the current connection has been connected to * a remote host. This will happen both if the connection has been * actively opened (with uip_connect()) or passively opened (with * uip_listen()). + * + * \hideinitializer */ #define uip_connected() (uip_flags & UIP_CONNECTED) -/* uip_closed(): +/** + * Has the connection been closed by the other end? * * Is non-zero if the connection has been closed by the remote - * host. The application may do the necessary clean-ups. + * host. The application may then do the necessary clean-ups. + * + * \hideinitializer */ #define uip_closed() (uip_flags & UIP_CLOSE) -/* uip_aborted(): +/** + * Has the connection been aborted by the other end? * * Non-zero if the current connection has been aborted (reset) by the * remote host. + * + * \hideinitializer */ #define uip_aborted() (uip_flags & UIP_ABORT) -/* uip_timedout(): +/** + * Has the connection timed out? * * Non-zero if the current connection has been aborted due to too many * retransmissions. + * + * \hideinitializer */ #define uip_timedout() (uip_flags & UIP_TIMEDOUT) -/* uip_rexmit(): +/** + * Do we need to retransmit previously data? * * Reduces to non-zero if the previously sent data has been lost in * the network, and the application should retransmit it. The - * application should set the uip_appdata buffer and the uip_len - * variable just as it did the last time this data was to be - * transmitted. + * application should send the exact same data as it did the last + * time, using the uip_send() function. + * + * \hideinitializer */ #define uip_rexmit() (uip_flags & UIP_REXMIT) -/* uip_poll(): +/** + * Is the connection being polled by uIP? * * Is non-zero if the reason the application is invoked is that the * current connection has been idle for a while and should be * polled. + * + * The polling event can be used for sending data without having to + * wait for the remote host to send data. + * + * \hideinitializer */ #define uip_poll() (uip_flags & UIP_POLL) -/* uip_mss(): - * - * Gives the current maxium segment size (MSS) of the current +/** + * Get the initial maxium segment size (MSS) of the current * connection. + * + * \hideinitializer + */ +#define uip_initialmss() (uip_conn->initialmss) + +/** + * Get the current maxium segment size that can be sent on the current + * connection. + * + * The current maxiumum segment size that can be sent on the + * connection is computed from the receiver's window and the MSS of + * the connection (which also is available by calling + * uip_initialmss()). + * + * \hideinitializer */ #define uip_mss() (uip_conn->mss) +/** + * Set up a new UDP connection. + * + * \param ripaddr A pointer to a 4-byte structure representing the IP + * address of the remote host. + * + * \param rport The remote port number in network byte order. + * + * \return The uip_udp_conn structure for the new connection or NULL + * if no connection could be allocated. + */ +struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport); + +/** + * Removed a UDP connection. + * + * \param conn A pointer to the uip_udp_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_udp_remove(conn) (conn)->lport = 0 + +/** + * Send a UDP datagram of length len on the current connection. + * + * This function can only be called in response to a UDP event (poll + * or newdata). The data must be present in the uip_buf buffer, at the + * place pointed to by the uip_appdata pointer. + * + * \param len The length of the data in the uip_buf buffer. + * + * \hideinitializer + */ +#define uip_udp_send(len) uip_slen = (len) + +/** @} */ /* uIP convenience and converting functions. */ -/* uip_ipaddr(&ipaddr, addr0,addr1,addr2,addr3): +/** + * \defgroup uipconvfunc uIP conversion functions + * @{ * - * Packs an IP address into a two element 16-bit array. Such arrays - * are used to represent IP addresses in uIP. + * These functions can be used for converting between different data + * formats used by uIP. + */ + +/** + * Pack an IP address into a 4-byte array which is used by uIP to + * represent IP addresses. + * + * Example: + \code + u16_t ipaddr[2]; + + uip_ipaddr(&ipaddr, 192,168,1,2); + \endcode + * + * \param addr A pointer to a 4-byte array that will be filled in with + * the IP addres. + * \param addr0 The first octet of the IP address. + * \param addr1 The second octet of the IP address. + * \param addr2 The third octet of the IP address. + * \param addr3 The forth octet of the IP address. + * + * \hideinitializer */ #define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ - (addr)[0] = htons(((addr0) << 8) | (addr1)); \ - (addr)[1] = htons(((addr2) << 8) | (addr3)); \ + (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ + (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ } while(0) -/* htons(), ntohs(): +/** + * Convert 16-bit quantity from host byte order to network byte order. * - * Macros for converting 16-bit quantities between host and network - * byte order. + * This macro is primarily used for converting constants from host + * byte order to network byte order. For converting variables to + * network byte order, use the htons() function instead. + * + * \hideinitializer + */ +#ifndef HTONS +# if BYTE_ORDER == BIG_ENDIAN +# define HTONS(n) (n) +# else /* BYTE_ORDER == BIG_ENDIAN */ +# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) +# endif /* BYTE_ORDER == BIG_ENDIAN */ +#endif /* HTONS */ + +/** + * Convert 16-bit quantity from host byte order to network byte order. + * + * This function is primarily used for converting variables from host + * byte order to network byte order. For converting constants to + * network byte order, use the HTONS() macro instead. */ #ifndef htons -# if BYTE_ORDER == BIG_ENDIAN -# define htons(n) (n) -# else /* BYTE_ORDER == BIG_ENDIAN */ -# define htons(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) -# endif /* BYTE_ORDER == BIG_ENDIAN */ +u16_t htons(u16_t val); #endif /* htons */ -#define ntohs(n) htons(n) +/** @} */ - -/*-----------------------------------------------------------------------------------*/ -/* The following global variables are used for passing parameters - * between uIP, the network device driver and the application. */ -/*-----------------------------------------------------------------------------------*/ - -/* u8_t uip_buf[UIP_BUFSIZE]: - * - * The uip_buf array is used to hold incoming and outgoing - * packets. The device driver fills this with incoming packets. - */ -extern u8_t uip_buf[UIP_BUFSIZE]; - -/* u8_t *uip_appdata: +/** + * Pointer to the application data in the packet buffer. * * This pointer points to the application data when the application is - * called. If the application wishes to send data, this is where the - * application should write it. The application can also point this to - * another location. + * called. If the application wishes to send data, the application may + * use this space to write the data into before calling uip_send(). */ -extern volatile u8_t *uip_appdata; +extern volatile u8_t *uip_appdata; +extern volatile u8_t *uip_sappdata; + +#if UIP_URGDATA > 0 +/* u8_t *uip_urgdata: + * + * This pointer points to any urgent data that has been received. Only + * present if compiled with support for urgent data (UIP_URGDATA). + */ +extern volatile u8_t *uip_urgdata; +#endif /* UIP_URGDATA > 0 */ + /* u[8|16]_t uip_len: * @@ -273,23 +751,15 @@ extern volatile u8_t *uip_appdata; * output function is called, uip_len should contain the length of the * outgoing packet. */ -#if UIP_BUFSIZE > 255 -extern volatile u16_t uip_len; -#else -extern volatile u8_t uip_len; -#endif /* UIP_BUFSIZE > 255 */ +extern volatile u16_t uip_len, uip_slen; -/* struct uip_conn *uip_conn: - * - * When the application is called, uip_conn will point to the current - * conntection, the one that should be processed by the - * application. The uip_conns[] array is a list containing all - * connections. - */ -extern struct uip_conn *uip_conn; -extern struct uip_conn uip_conns[UIP_CONNS]; +#if UIP_URGDATA > 0 +extern volatile u8_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ -/* struct uip_conn: + +/** + * Representation of a uIP TCP connection. * * The uip_conn structure is used for identifying a connection. All * but one field in the structure are to be considered read-only by an @@ -299,69 +769,122 @@ extern struct uip_conn uip_conns[UIP_CONNS]; * configured in the "uipopt.h" header file. */ struct uip_conn { - u8_t tcpstateflags; /* TCP state and flags. */ - u16_t lport, rport; /* The local and the remote port. */ - u16_t ripaddr[2]; /* The IP address of the remote peer. */ - u8_t rcv_nxt[4]; /* The sequence number that we expect to receive - next. */ - u8_t snd_nxt[4]; /* The sequence number that was last sent by - us. */ - u8_t ack_nxt[4]; /* The sequence number that should be ACKed by - next ACK from peer. */ -#if UIP_TCP_MSS > 255 - u16_t mss; /* Maximum segment size for the connection. */ -#else - u8_t mss; -#endif /* UIP_TCP_MSS */ - u8_t timer; /* The retransmission timer. */ - u8_t nrtx; /* Counts the number of retransmissions for a - particular segment. */ + u16_t ripaddr[2]; /**< The IP address of the remote host. */ - u8_t appstate[UIP_APPSTATE_SIZE]; + u16_t lport; /**< The local TCP port, in network byte order. */ + u16_t rport; /**< The local remote TCP port, in network byte + order. */ + + u8_t rcv_nxt[4]; /**< The sequence number that we expect to + receive next. */ + u8_t snd_nxt[4]; /**< The sequence number that was last sent by + us. */ + u16_t len; /**< Length of the data that was previously sent. */ + u16_t mss; /**< Current maximum segment size for the + connection. */ + u16_t initialmss; /**< Initial maximum segment size for the + connection. */ + u8_t sa; /**< Retransmission time-out calculation state + variable. */ + u8_t sv; /**< Retransmission time-out calculation state + variable. */ + u8_t rto; /**< Retransmission time-out. */ + u8_t tcpstateflags; /**< TCP state and flags. */ + u8_t timer; /**< The retransmission timer. */ + u8_t nrtx; /**< The number of retransmissions for the last + segment sent. */ + + /** The application state. */ + u8_t appstate[UIP_APPSTATE_SIZE]; }; -/* struct uip_stats: + +/* Pointer to the current connection. */ +extern struct uip_conn *uip_conn; +/* The array containing all uIP connections. */ +extern struct uip_conn uip_conns[UIP_CONNS]; +/** + * \addtogroup uiparch + * @{ + */ + +/** + * 4-byte array used for the 32-bit sequence number calculations. + */ +extern volatile u8_t uip_acc32[4]; + +/** @} */ + + +#if UIP_UDP +/** + * Representation of a uIP UDP connection. + */ +struct uip_udp_conn { + u16_t ripaddr[2]; /**< The IP address of the remote peer. */ + u16_t lport; /**< The local port number in network byte order. */ + u16_t rport; /**< The remote port number in network byte order. */ +}; + +extern struct uip_udp_conn *uip_udp_conn; +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +/** + * The structure holding the TCP/IP statistics that are gathered if + * UIP_STATISTICS is set to 1. * - * Contains statistics about the TCP/IP stack. */ struct uip_stats { struct { - u16_t drop; - u16_t recv; - u16_t sent; - u16_t vhlerr; /* Number of packets dropped due to wrong IP version - or header length. */ - u16_t hblenerr; /* Number of packets dropped due to wrong IP length, - high byte. */ - u16_t lblenerr; /* Number of packets dropped due to wrong IP length, - low byte. */ - u16_t fragerr; /* Number of packets dropped since they were IP - fragments. */ - u16_t chkerr; /* Number of packets dropped due to IP checksum errors. */ - u16_t protoerr; /* Number of packets dropped since they were neither - ICMP nor TCP. */ - } ip; + uip_stats_t drop; /**< Number of dropped packets at the IP + layer. */ + uip_stats_t recv; /**< Number of received packets at the IP + layer. */ + uip_stats_t sent; /**< Number of sent packets at the IP + layer. */ + uip_stats_t vhlerr; /**< Number of packets dropped due to wrong + IP version or header length. */ + uip_stats_t hblenerr; /**< Number of packets dropped due to wrong + IP length, high byte. */ + uip_stats_t lblenerr; /**< Number of packets dropped due to wrong + IP length, low byte. */ + uip_stats_t fragerr; /**< Number of packets dropped since they + were IP fragments. */ + uip_stats_t chkerr; /**< Number of packets dropped due to IP + checksum errors. */ + uip_stats_t protoerr; /**< Number of packets dropped since they + were neither ICMP, UDP nor TCP. */ + } ip; /**< IP statistics. */ struct { - u16_t drop; - u16_t recv; - u16_t sent; - u16_t typeerr; - } icmp; + uip_stats_t drop; /**< Number of dropped ICMP packets. */ + uip_stats_t recv; /**< Number of received ICMP packets. */ + uip_stats_t sent; /**< Number of sent ICMP packets. */ + uip_stats_t typeerr; /**< Number of ICMP packets with a wrong + type. */ + } icmp; /**< ICMP statistics. */ struct { - u16_t drop; - u16_t recv; - u16_t sent; - u16_t chkerr; - u16_t ackerr; - u16_t rst; - u16_t rexmit; - u16_t syndrop; /* Number of dropped SYNs due to too few - connections was avaliable. */ - u16_t synrst; /* Number of SYNs for closed ports, triggering a - RST. */ - } tcp; + uip_stats_t drop; /**< Number of dropped TCP segments. */ + uip_stats_t recv; /**< Number of recived TCP segments. */ + uip_stats_t sent; /**< Number of sent TCP segments. */ + uip_stats_t chkerr; /**< Number of TCP segments with a bad + checksum. */ + uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK + number. */ + uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ + uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ + uip_stats_t syndrop; /**< Number of dropped SYNs due to too few + connections was avaliable. */ + uip_stats_t synrst; /**< Number of SYNs for closed ports, + triggering a RST. */ + } tcp; /**< TCP statistics. */ }; +/** + * The uIP TCP/IP statistics. + * + * This is the variable in which the uIP TCP/IP statistics are gathered. + */ extern struct uip_stats uip_stat; @@ -382,8 +905,7 @@ extern volatile u8_t uip_flags; before calling the application callback. The UIP_ACKDATA and UIP_NEWDATA flags may both be set at the same time, whereas the others are mutualy exclusive. Note that these flags should *NOT* be - accessed directly, but through the uip_has and uip_in - functions/macros. */ + accessed directly, but through the uIP functions/macros. */ #define UIP_ACKDATA 1 /* Signifies that the outstanding data was acked and the application should send @@ -433,6 +955,9 @@ void uip_process(u8_t flag); uip_len. */ #define UIP_TIMER 2 /* Tells uIP that the periodic timer has fired. */ +#if UIP_UDP +#define UIP_UDP_TIMER 3 +#endif /* UIP_UDP */ /* The TCP states used in the uip_conn->tcpstateflags. */ #define CLOSED 0 @@ -446,8 +971,9 @@ void uip_process(u8_t flag); #define LAST_ACK 8 #define TS_MASK 15 -#define UIP_OUTSTANDING 16 -#define UIP_STOPPED 32 +#define UIP_STOPPED 16 + +#define UIP_TCPIP_HLEN 40 /* The TCP and IP headers. */ typedef struct { @@ -462,6 +988,7 @@ typedef struct { u16_t ipchksum; u16_t srcipaddr[2], destipaddr[2]; + /* TCP header. */ u16_t srcport, destport; @@ -470,17 +997,64 @@ typedef struct { tcpoffset, flags, wnd[2]; - u16_t tcpchksum, - urgp; + u16_t tcpchksum; + u8_t urgp[2]; u8_t optdata[4]; } uip_tcpip_hdr; +/* The ICMP and IP headers. */ +typedef struct { + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; + /* ICMP (echo) header. */ + u8_t type, icode; + u16_t icmpchksum; + u16_t id, seqno; +} uip_icmpip_hdr; + + +/* The UDP and IP headers. */ +typedef struct { + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; + + /* UDP header. */ + u16_t srcport, + destport; + u16_t udplen; + u16_t udpchksum; +} uip_udpip_hdr; + +#define UIP_PROTO_ICMP 1 +#define UIP_PROTO_TCP 6 +#define UIP_PROTO_UDP 17 + +#if UIP_FIXEDADDR +extern const u16_t uip_hostaddr[2]; +#else /* UIP_FIXEDADDR */ +extern u16_t uip_hostaddr[2]; +#endif /* UIP_FIXEDADDR */ #endif /* __UIP_H__ */ - - - - +/** @} */ diff --git a/uip/uip_arch.h b/uip/uip_arch.h new file mode 100644 index 0000000..947d84c --- /dev/null +++ b/uip/uip_arch.h @@ -0,0 +1,130 @@ +/** + * \defgroup uiparch Architecture specific uIP functions + * @{ + * + * The functions in the architecture specific module implement the IP + * check sum and 32-bit additions. + * + * The IP checksum calculation is the most computationally expensive + * operation in the TCP/IP stack and it therefore pays off to + * implement this in efficient assembler. The purpose of the uip-arch + * module is to let the checksum functions to be implemented in + * architecture specific assembler. + * + */ + +/** + * \file + * Declarations of architecture specific functions. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2001, 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ + * + */ + +#ifndef __UIP_ARCH_H__ +#define __UIP_ARCH_H__ + +#include "uip.h" + +/** + * Carry out a 32-bit addition. + * + * Because not all architectures for which uIP is intended has native + * 32-bit arithmetic, uIP uses an external C function for doing the + * required 32-bit additions in the TCP protocol processing. This + * function should add the two arguments and place the result in the + * global variable uip_acc32. + * + * \note The 32-bit integer pointed to by the op32 parameter and the + * result in the uip_acc32 variable are in network byte order (big + * endian). + * + * \param op32 A pointer to a 4-byte array representing a 32-bit + * integer in network byte order (big endian). + * + * \param op16 A 16-bit integer in host byte order. + */ +void uip_add32(u8_t *op32, u16_t op16); + +/** + * Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * \note This function is not called in the current version of uIP, + * but future versions might make use of it. + * + * \param buf A pointer to the buffer over which the checksum is to be + * computed. + * + * \param len The length of the buffer over which the checksum is to + * be computed. + * + * \return The Internet checksum of the buffer. + */ +u16_t uip_chksum(u16_t *buf, u16_t len); + +/** + * Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * \return The IP header checksum of the IP header in the uip_buf + * buffer. + */ +u16_t uip_ipchksum(void); + +/** + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * \note The uip_appdata pointer that points to the packet data may + * point anywhere in memory, so it is not possible to simply calculate + * the Internet checksum of the contents of the uip_buf buffer. + * + * \return The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_tcpchksum(void); + +/** @} */ + +#endif /* __UIP_ARCH_H__ */ diff --git a/uip/uip_arp.c b/uip/uip_arp.c index 2bc53da..6752925 100644 --- a/uip/uip_arp.c +++ b/uip/uip_arp.c @@ -1,5 +1,31 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uiparp uIP Address Resolution Protocol + * @{ + * + * The Address Resolution Protocol ARP is used for mapping between IP + * addresses and link level addresses such as the Ethernet MAC + * addresses. ARP uses broadcast queries to ask for the link level + * address of a known IP address and the host which is configured with + * the IP address for which the query was meant, will respond with its + * link level address. + * + * \note This ARP implementation only supports Ethernet. + */ + +/** + * \file + * Implementation of the ARP Address Resolution Protocol. + * \author Adam Dunkels + * + */ + /* - * Copyright (c) 2001-2002, Adam Dunkels. + * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +36,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,13 +54,15 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip_arp.c,v 1.3 2002/01/13 21:12:41 adam Exp $ + * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ * */ #include "uip_arp.h" +#include + struct arp_hdr { struct uip_eth_hdr ethhdr; u16_t hwtype; @@ -77,41 +102,56 @@ struct arp_entry { u8_t time; }; -static const struct uip_eth_addr ethaddr = {{UIP_ETHADDR0, - UIP_ETHADDR1, - UIP_ETHADDR2, - UIP_ETHADDR3, - UIP_ETHADDR4, - UIP_ETHADDR5}}; +struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, + UIP_ETHADDR1, + UIP_ETHADDR2, + UIP_ETHADDR3, + UIP_ETHADDR4, + UIP_ETHADDR5}}; static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; static u16_t ipaddr[2]; static u8_t i, c; -static u8_t time; +static u8_t arptime; static u8_t tmpage; #define BUF ((struct arp_hdr *)&uip_buf[0]) #define IPBUF ((struct ethip_hdr *)&uip_buf[0]) /*-----------------------------------------------------------------------------------*/ +/** + * Initialize the ARP module. + * + */ +/*-----------------------------------------------------------------------------------*/ void uip_arp_init(void) { for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { - arp_table[i].ipaddr[0] = - arp_table[i].ipaddr[1] = 0; + memset(arp_table[i].ipaddr, 0, 4); } } /*-----------------------------------------------------------------------------------*/ +/** + * Periodic ARP processing function. + * + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. + * + */ +/*-----------------------------------------------------------------------------------*/ void uip_arp_timer(void) { - ++time; + struct arp_entry *tabptr; + + ++arptime; for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { - if((arp_table[i].ipaddr[0] | arp_table[i].ipaddr[1]) != 0 && - time - arp_table[i].time >= UIP_ARP_MAXAGE) { - arp_table[i].ipaddr[0] = - arp_table[i].ipaddr[1] = 0; + tabptr = &arp_table[i]; + if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && + arptime - tabptr->time >= UIP_ARP_MAXAGE) { + memset(tabptr->ipaddr, 0, 4); } } @@ -120,25 +160,26 @@ uip_arp_timer(void) static void uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) { + register struct arp_entry *tabptr; /* Walk through the ARP mapping table and try to find an entry to update. If none is found, the IP -> MAC address mapping is inserted in the ARP table. */ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { - + + tabptr = &arp_table[i]; /* Only check those entries that are actually in use. */ - if(arp_table[i].ipaddr[0] != 0 && - arp_table[i].ipaddr[1] != 0) { + if(tabptr->ipaddr[0] != 0 && + tabptr->ipaddr[1] != 0) { /* Check if the source IP address of the incoming packet matches the IP address in this ARP table entry. */ - if(ipaddr[0] == arp_table[i].ipaddr[0] && - ipaddr[1] == arp_table[i].ipaddr[1]) { + if(ipaddr[0] == tabptr->ipaddr[0] && + ipaddr[1] == tabptr->ipaddr[1]) { /* An old entry found, update this and return. */ - for(c = 0; c < 6; ++c) { - arp_table[i].ethaddr.addr[c] = ethaddr->addr[c]; - } - arp_table[i].time = time; + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; + return; } } @@ -149,9 +190,11 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) /* First, we try to find an unused entry in the ARP table. */ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { - if(arp_table[i].ipaddr[0] == 0 && - arp_table[i].ipaddr[1] == 0) - break; + tabptr = &arp_table[i]; + if(tabptr->ipaddr[0] == 0 && + tabptr->ipaddr[1] == 0) { + break; + } } /* If no unused entry is found, we try to find the oldest entry and @@ -160,8 +203,9 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) tmpage = 0; c = 0; for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { - if(time - arp_table[i].time > tmpage) { - tmpage = time - arp_table[i].time; + tabptr = &arp_table[i]; + if(arptime - tabptr->time > tmpage) { + tmpage = arptime - tabptr->time; c = i; } } @@ -170,34 +214,66 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) /* Now, i is the ARP table entry which we will fill with the new information. */ - arp_table[i].ipaddr[0] = ipaddr[0]; - arp_table[i].ipaddr[1] = ipaddr[1]; - for(c = 0; c < 6; ++c) { - arp_table[i].ethaddr.addr[c] = ethaddr->addr[c]; - } - arp_table[i].time = time; + memcpy(tabptr->ipaddr, ipaddr, 4); + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; } /*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming IP packets + * + * This function should be called by the device driver when an IP + * packet has been received. The function will check if the address is + * in the ARP cache, and if so the ARP cache entry will be + * refreshed. If no ARP cache entry was found, a new one is created. + * + * This function expects an IP packet with a prepended Ethernet header + * in the uip_buf[] buffer, and the length of the packet in the global + * variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ void uip_arp_ipin(void) { - + uip_len -= sizeof(struct uip_eth_hdr); + /* Only insert/update an entry if the source IP address of the incoming IP packet comes from a host on the local network. */ - if((IPBUF->srcipaddr[0] & htons((UIP_NETMASK0 << 8) | UIP_NETMASK1)) != - (htons((UIP_IPADDR0 << 8) | UIP_IPADDR1) - & htons((UIP_NETMASK0 << 8) | UIP_NETMASK1))) + if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) != + (uip_hostaddr[0] & uip_arp_netmask[0])) { return; - if((IPBUF->srcipaddr[1] & htons((UIP_NETMASK2 << 8) | UIP_NETMASK3)) != - (htons((UIP_IPADDR2 << 8) | UIP_IPADDR3) - & htons((UIP_NETMASK2 << 8) | UIP_NETMASK3))) + } + if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != + (uip_hostaddr[1] & uip_arp_netmask[1])) { return; - + } uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); return; } /*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming ARP packets. + * + * This function should be called by the device driver when an ARP + * packet has been received. The function will act differently + * depending on the ARP packet type: if it is a reply for a request + * that we previously sent out, the ARP cache will be filled in with + * the values from the ARP reply. If the incoming ARP packet is an ARP + * request for our IP address, an ARP reply packet is created and put + * into the uip_buf[] buffer. + * + * When the function returns, the value of the global variable uip_len + * indicates whether the device driver should send out a packet or + * not. If uip_len is zero, no packet should be sent. If uip_len is + * non-zero, it contains the length of the outbound packet that is + * present in the uip_buf[] buffer. + * + * This function expects an ARP packet with a prepended Ethernet + * header in the uip_buf[] buffer, and the length of the packet in the + * global variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ void uip_arp_arpin(void) { @@ -210,35 +286,33 @@ uip_arp_arpin(void) uip_len = 0; switch(BUF->opcode) { - case htons(ARP_REQUEST): + case HTONS(ARP_REQUEST): /* ARP request. If it asked for our address, we send out a reply. */ - if(BUF->dipaddr[0] == htons((UIP_IPADDR0 << 8) | UIP_IPADDR1) && - BUF->dipaddr[1] == htons((UIP_IPADDR2 << 8) | UIP_IPADDR3)) { + if(BUF->dipaddr[0] == uip_hostaddr[0] && + BUF->dipaddr[1] == uip_hostaddr[1]) { /* The reply opcode is 2. */ - BUF->opcode = htons(2); - BUF->dhwaddr = BUF->shwaddr; - - for(c = 0; c < 6; ++c) { - BUF->shwaddr.addr[c] = - BUF->ethhdr.src.addr[c] = ethaddr.addr[c]; - BUF->ethhdr.dest.addr[c] = BUF->dhwaddr.addr[c]; - } + BUF->opcode = HTONS(2); + memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); + BUF->dipaddr[0] = BUF->sipaddr[0]; BUF->dipaddr[1] = BUF->sipaddr[1]; - BUF->sipaddr[0] = htons((UIP_IPADDR0 << 8) | UIP_IPADDR1); - BUF->sipaddr[1] = htons((UIP_IPADDR2 << 8) | UIP_IPADDR3); + BUF->sipaddr[0] = uip_hostaddr[0]; + BUF->sipaddr[1] = uip_hostaddr[1]; - BUF->ethhdr.type = htons(UIP_ETHTYPE_ARP); + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); uip_len = sizeof(struct arp_hdr); } break; - case htons(ARP_REPLY): + case HTONS(ARP_REPLY): /* ARP reply. We insert or update the ARP table if it was meant for us. */ - if(BUF->dipaddr[0] == htons((UIP_IPADDR0 << 8) | UIP_IPADDR1) && - BUF->dipaddr[1] == htons((UIP_IPADDR2 << 8) | UIP_IPADDR3)) { + if(BUF->dipaddr[0] == uip_hostaddr[0] && + BUF->dipaddr[1] == uip_hostaddr[1]) { uip_arp_update(BUF->sipaddr, &BUF->shwaddr); } @@ -248,9 +322,37 @@ uip_arp_arpin(void) return; } /*-----------------------------------------------------------------------------------*/ +/** + * Prepend Ethernet header to an outbound IP packet and see if we need + * to send out an ARP request. + * + * This function should be called before sending out an IP packet. The + * function checks the destination IP address of the IP packet to see + * what Ethernet MAC address that should be used as a destination MAC + * address on the Ethernet. + * + * If the destination IP address is in the local network (determined + * by logical ANDing of netmask and our IP address), the function + * checks the ARP cache to see if an entry for the destination IP + * address is found. If so, an Ethernet header is prepended and the + * function returns. If no ARP cache entry is found for the + * destination IP address, the packet in the uip_buf[] is replaced by + * an ARP request packet for the IP address. The IP packet is dropped + * and it is assumed that they higher level protocols (e.g., TCP) + * eventually will retransmit the dropped packet. + * + * If the destination IP address is not on the local network, the IP + * address of the default router is used instead. + * + * When the function returns, a packet is present in the uip_buf[] + * buffer, and the length of the packet is in the global variable + * uip_len. + */ +/*-----------------------------------------------------------------------------------*/ void uip_arp_out(void) { + struct arp_entry *tabptr; /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the local network, we use the default router's IP address instead. @@ -259,17 +361,15 @@ uip_arp_out(void) packet with an ARP request for the IP address. */ /* Check if the destination address is on the local network. */ - if((IPBUF->destipaddr[0] & htons((UIP_NETMASK0 << 8) | UIP_NETMASK1)) != - (htons((UIP_IPADDR0 << 8) | UIP_IPADDR1) - & htons((UIP_NETMASK0 << 8) | UIP_NETMASK1)) || - (IPBUF->destipaddr[1] & htons((UIP_NETMASK2 << 8) | UIP_NETMASK3)) != - (htons((UIP_IPADDR2 << 8) | UIP_IPADDR3) - & htons((UIP_NETMASK2 << 8) | UIP_NETMASK3))) { + if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != + (uip_hostaddr[0] & uip_arp_netmask[0]) || + (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != + (uip_hostaddr[1] & uip_arp_netmask[1])) { /* Destination address was not on the local network, so we need to use the default router's IP address instead of the destination address when determining the MAC address. */ - ipaddr[0] = htons((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1); - ipaddr[1] = htons((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3); + ipaddr[0] = uip_arp_draddr[0]; + ipaddr[1] = uip_arp_draddr[1]; } else { /* Else, we use the destination IP address. */ ipaddr[0] = IPBUF->destipaddr[0]; @@ -277,8 +377,9 @@ uip_arp_out(void) } for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { - if(ipaddr[0] == arp_table[i].ipaddr[0] && - ipaddr[1] == arp_table[i].ipaddr[1]) + tabptr = &arp_table[i]; + if(ipaddr[0] == tabptr->ipaddr[0] && + ipaddr[1] == tabptr->ipaddr[1]) break; } @@ -286,23 +387,21 @@ uip_arp_out(void) /* The destination address was not in our ARP table, so we overwrite the IP packet with an ARP request. */ - for(c = 0; c < 6; ++c) { - BUF->ethhdr.dest.addr[c] = 0xff; /* Broadcast ARP request. */ - BUF->ethhdr.src.addr[c] = - BUF->shwaddr.addr[c] = ethaddr.addr[c]; - BUF->dhwaddr.addr[c] = 0; - } + memset(BUF->ethhdr.dest.addr, 0xff, 6); + memset(BUF->dhwaddr.addr, 0x00, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); BUF->dipaddr[0] = ipaddr[0]; BUF->dipaddr[1] = ipaddr[1]; - BUF->sipaddr[0] = htons((UIP_IPADDR0 << 8) | UIP_IPADDR1); - BUF->sipaddr[1] = htons((UIP_IPADDR2 << 8) | UIP_IPADDR3); - BUF->opcode = htons(ARP_REQUEST); /* ARP request. */ - BUF->hwtype = htons(ARP_HWTYPE_ETH); - BUF->protocol = htons(UIP_ETHTYPE_IP); + BUF->sipaddr[0] = uip_hostaddr[0]; + BUF->sipaddr[1] = uip_hostaddr[1]; + BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ + BUF->hwtype = HTONS(ARP_HWTYPE_ETH); + BUF->protocol = HTONS(UIP_ETHTYPE_IP); BUF->hwlen = 6; BUF->protolen = 4; - BUF->ethhdr.type = htons(UIP_ETHTYPE_ARP); + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; @@ -311,16 +410,14 @@ uip_arp_out(void) } /* Build an ethernet header. */ - for(c = 0; c < 6; ++c) { - IPBUF->ethhdr.dest.addr[c] = arp_table[i].ethaddr.addr[c]; - IPBUF->ethhdr.src.addr[0] = ethaddr.addr[c]; - } - IPBUF->ethhdr.type = htons(UIP_ETHTYPE_IP); + memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + + IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); uip_len += sizeof(struct uip_eth_hdr); } /*-----------------------------------------------------------------------------------*/ - - - +/** @} */ +/** @} */ diff --git a/uip/uip_arp.h b/uip/uip_arp.h index d8cab5c..0371cd6 100644 --- a/uip/uip_arp.h +++ b/uip/uip_arp.h @@ -1,5 +1,22 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \addtogroup uiparp + * @{ + */ + +/** + * \file + * Macros and definitions for the ARP module. + * \author Adam Dunkels + */ + + /* - * Copyright (c) 2001-2002, Adam Dunkels. + * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +27,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +45,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip_arp.h,v 1.2 2002/01/11 18:54:35 adam Exp $ + * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ * */ @@ -40,10 +54,19 @@ #include "uip.h" + +/** + * Representation of a 48-bit Ethernet address. + */ struct uip_eth_addr { u8_t addr[6]; }; - + +extern struct uip_eth_addr uip_ethaddr; + +/** + * The Ethernet header. + */ struct uip_eth_hdr { struct uip_eth_addr dest; struct uip_eth_addr src; @@ -52,6 +75,8 @@ struct uip_eth_hdr { #define UIP_ETHTYPE_ARP 0x0806 #define UIP_ETHTYPE_IP 0x0800 +#define UIP_ETHTYPE_IP6 0x86dd + /* The uip_arp_init() function must be called before any of the other ARP functions. */ @@ -88,4 +113,89 @@ void uip_arp_out(void); is responsible for flushing old entries in the ARP table. */ void uip_arp_timer(void); +/** @} */ + +/** + * \addtogroup uipconffunc + * @{ + */ + +/** + * Set the default router's IP address. + * + * \param addr A pointer to a 4-byte array containing the IP address + * of the default router. + * + * \hideinitializer + */ +#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ + uip_arp_draddr[1] = addr[1]; } while(0) + +/** + * Set the netmask. + * + * \param addr A pointer to a 4-byte array containing the IP address + * of the netmask. + * + * \hideinitializer + */ +#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ + uip_arp_netmask[1] = addr[1]; } while(0) + + +/** + * Get the default router's IP address. + * + * \param addr A pointer to a 4-byte array that will be filled in with + * the IP address of the default router. + * + * \hideinitializer + */ +#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ + addr[1] = uip_arp_draddr[1]; } while(0) + +/** + * Get the netmask. + * + * \param addr A pointer to a 4-byte array that will be filled in with + * the value of the netmask. + * + * \hideinitializer + */ +#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ + addr[1] = uip_arp_netmask[1]; } while(0) + + +/** + * Specifiy the Ethernet MAC address. + * + * The ARP code needs to know the MAC address of the Ethernet card in + * order to be able to respond to ARP queries and to generate working + * Ethernet headers. + * + * \note This macro only specifies the Ethernet MAC address to the ARP + * code. It cannot be used to change the MAC address of the Ethernet + * card. + * + * \param eaddr A pointer to a struct uip_eth_addr containing the + * Ethernet MAC address of the Ethernet card. + * + * \hideinitializer + */ +#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ + uip_ethaddr.addr[1] = eaddr.addr[1];\ + uip_ethaddr.addr[2] = eaddr.addr[2];\ + uip_ethaddr.addr[3] = eaddr.addr[3];\ + uip_ethaddr.addr[4] = eaddr.addr[4];\ + uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) + +/** @} */ + +/** + * \internal Internal variables that are set using the macros + * uip_setdraddr and uip_setnetmask. + */ +extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; #endif /* __UIP_ARP_H__ */ + + diff --git a/unix/Makefile b/unix/Makefile index 267d97a..8f99cc4 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -30,34 +30,39 @@ # # This file is part of the uIP TCP/IP stack. # -# $Id: Makefile,v 1.2 2002/01/10 07:34:41 adam Exp $ +# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ # CC=gcc -CFLAGS=-Wall -g -fpack-struct -I../uip -I. -I../apps/httpd -O1 +CFLAGS=-Wall -g -I../uip -I. -I../apps/httpd -I../apps/resolv -I../apps/webclient -I../apps/smtp -I../apps/telnet -fpack-struct %.o: $(CC) $(CFLAGS) -c $(<:.o=.c) -uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o cgi.o +uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o cgi.o -httpd.o: ../apps/httpd/httpd.c ../apps/httpd/httpd.h ../uip/uip.h \ - uipopt.h ../apps/httpd/fs.h -cgi.o: ../apps/httpd/cgi.c ../uip/uip.h uipopt.h ../apps/httpd/httpd.h \ - ../apps/httpd/cgi.h ../apps/httpd/fs.h -fs.o: ../apps/httpd/fs.c ../uip/uip.h uipopt.h ../apps/httpd/httpd.h \ - ../apps/httpd/fs.h ../apps/httpd/fsdata.h \ - ../apps/httpd/fsdata.c tapdev.o: tapdev.c uipopt.h main.o: main.c ../uip/uip.h uipopt.h ../apps/httpd/httpd.h \ tapdev.h -uip_arch.o: uip_arch.c uip_arch.h ../uip/uip.h uipopt.h \ +uip_arch.o: uip_arch.c ../uip/uip_arch.h ../uip/uip.h uipopt.h \ ../apps/httpd/httpd.h uip.o: ../uip/uip.c ../uip/uip.h uipopt.h ../apps/httpd/httpd.h uip_arp.o: ../uip/uip_arp.c ../uip/uip_arp.h ../uip/uip.h uipopt.h \ - ../apps/httpd/httpd.h + ../apps/httpd/httpd.h + $(CC) -o uip_arp.o $(CFLAGS) -fpack-struct -c ../uip/uip_arp.c + + +cgi.o: ../apps/httpd/cgi.c ../uip/uip.h uipopt.h ../apps/smtp/smtp.h \ + ../apps/httpd/cgi.h ../apps/httpd/httpd.h ../apps/httpd/fs.h +fs.o: ../apps/httpd/fs.c ../uip/uip.h uipopt.h ../apps/smtp/smtp.h \ + ../apps/httpd/httpd.h ../apps/httpd/fs.h ../apps/httpd/fsdata.h \ + ../apps/httpd/fsdata.c +fsdata.o: ../apps/httpd/fsdata.c +httpd.o: ../apps/httpd/httpd.c ../uip/uip.h uipopt.h \ + ../apps/smtp/smtp.h ../apps/httpd/httpd.h ../apps/httpd/fs.h \ + ../apps/httpd/fsdata.h ../apps/httpd/cgi.h clean: rm -f *.o *~ *core uip diff --git a/unix/main.c b/unix/main.c index 92e3881..3930513 100644 --- a/unix/main.c +++ b/unix/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Adam Dunkels. + * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +10,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +28,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: main.c,v 1.2 2002/01/13 21:12:41 adam Exp $ + * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $ * */ @@ -40,18 +37,29 @@ #include "uip_arp.h" #include "tapdev.h" #include "httpd.h" +#include "telnet.h" #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + +#ifndef NULL +#define NULL (void *)0 +#endif /* NULL */ + /*-----------------------------------------------------------------------------------*/ int main(void) { u8_t i, arptimer; - - tapdev_init(); - uip_init(); - httpd_init(); + /* Initialize the device driver. */ + tapdev_init(); + + /* Initialize the uIP TCP/IP stack. */ + uip_init(); + + /* Initialize the HTTP server. */ + httpd_init(); + arptimer = 0; while(1) { @@ -64,15 +72,28 @@ main(void) if(uip_len == 0) { for(i = 0; i < UIP_CONNS; i++) { uip_periodic(i); - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ if(uip_len > 0) { uip_arp_out(); tapdev_send(); } } +#if UIP_UDP + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if(uip_len > 0) { + uip_arp_out(); + tapdev_send(); + } + } +#endif /* UIP_UDP */ + /* Call the ARP timer function every 10 seconds. */ if(++arptimer == 20) { uip_arp_timer(); @@ -82,7 +103,6 @@ main(void) } else { if(BUF->type == htons(UIP_ETHTYPE_IP)) { uip_arp_ipin(); - uip_len -= sizeof(struct uip_eth_hdr); uip_input(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable @@ -106,4 +126,9 @@ main(void) return 0; } /*-----------------------------------------------------------------------------------*/ - +void +uip_log(char *m) +{ + printf("uIP log message: %s\n", m); +} +/*-----------------------------------------------------------------------------------*/ diff --git a/unix/tapdev.c b/unix/tapdev.c index 923bf2e..aae0f91 100644 --- a/unix/tapdev.c +++ b/unix/tapdev.c @@ -31,7 +31,7 @@ * * Author: Adam Dunkels * - * $Id: tapdev.c,v 1.2 2002/01/11 18:54:35 adam Exp $ + * $Id: tapdev.c,v 1.7.2.1 2003/10/07 13:23:19 adam Exp $ */ @@ -58,7 +58,6 @@ #include "uip.h" -static int drop = 0; static int fd; static unsigned long lasttime; @@ -81,7 +80,7 @@ tapdev_init(void) struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP|IFF_NO_PI; - if (ioctl(tapif->fd, TUNSETIFF, (void *) &ifr) < 0) { + if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { perror(buf); exit(1); } @@ -127,15 +126,6 @@ tapdev_read(void) gettimeofday(&tv, &tz); lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec); - /* printf("--- tap_dev: tapdev_read: read %d bytes\n", ret);*/ - /* { - int i; - for(i = 0; i < 20; i++) { - printf("%x ", uip_buf[i]); - } - printf("\n"); - }*/ - /* check_checksum(uip_buf, ret);*/ return ret; } /*-----------------------------------------------------------------------------------*/ @@ -144,22 +134,35 @@ tapdev_send(void) { int ret; struct iovec iov[2]; - /* printf("tapdev_send: sending %d bytes\n", size);*/ - /* check_checksum(uip_buf, size);*/ - - /* drop++; - if(drop % 8 == 7) { - printf("Dropped a packet!\n"); - return; - }*/ - - iov[0].iov_base = uip_buf; - iov[0].iov_len = 40 + UIP_LLH_LEN; - iov[1].iov_base = (char *)uip_appdata; - iov[1].iov_len = uip_len - 40 + UIP_LLH_LEN; - - ret = writev(fd, iov, 2); +#ifdef linux + { + char tmpbuf[UIP_BUFSIZE]; + int i; + + for(i = 0; i < 40 + UIP_LLH_LEN; i++) { + tmpbuf[i] = uip_buf[i]; + } + + for(; i < uip_len; i++) { + tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; + } + + ret = write(fd, tmpbuf, uip_len); + } +#else + + if(uip_len < 40 + UIP_LLH_LEN) { + ret = write(fd, uip_buf, uip_len + UIP_LLH_LEN); + } else { + iov[0].iov_base = uip_buf; + iov[0].iov_len = 40 + UIP_LLH_LEN; + iov[1].iov_base = (char *)uip_appdata; + iov[1].iov_len = uip_len - (40 + UIP_LLH_LEN); + + ret = writev(fd, iov, 2); + } +#endif if(ret == -1) { perror("tap_dev: tapdev_send: writev"); exit(1); diff --git a/unix/tapdev.h b/unix/tapdev.h index 280bc52..5b947ef 100644 --- a/unix/tapdev.h +++ b/unix/tapdev.h @@ -10,10 +10,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +28,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: tapdev.h,v 1.1 2002/01/10 06:22:56 adam Exp $ + * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $ * */ diff --git a/unix/uip_arch.c b/unix/uip_arch.c index dcd9c81..cb3952b 100644 --- a/unix/uip_arch.c +++ b/unix/uip_arch.c @@ -10,10 +10,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,7 +28,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip_arch.c,v 1.1 2002/01/10 06:22:56 adam Exp $ + * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ * */ @@ -42,94 +39,37 @@ #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) #define IP_PROTO_TCP 6 -/*-----------------------------------------------------------------------------------*/ -#if UIP_BUFSIZE > 255 /*-----------------------------------------------------------------------------------*/ void -uip_add_rcv_nxt(u16_t n) +uip_add32(u8_t *op32, u16_t op16) { - uip_conn->rcv_nxt[3] += (n & 0xff); - uip_conn->rcv_nxt[2] += (n >> 8); - - if(uip_conn->rcv_nxt[2] < (n >> 8)) { - ++uip_conn->rcv_nxt[1]; - if(uip_conn->rcv_nxt[1] == 0) { - ++uip_conn->rcv_nxt[0]; + + uip_acc32[3] = op32[3] + (op16 & 0xff); + uip_acc32[2] = op32[2] + (op16 >> 8); + uip_acc32[1] = op32[1]; + uip_acc32[0] = op32[0]; + + if(uip_acc32[2] < (op16 >> 8)) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; } } - if(uip_conn->rcv_nxt[3] < (n & 0xff)) { - ++uip_conn->rcv_nxt[2]; - if(uip_conn->rcv_nxt[2] == 0) { - ++uip_conn->rcv_nxt[1]; - if(uip_conn->rcv_nxt[1] == 0) { - ++uip_conn->rcv_nxt[0]; + if(uip_acc32[3] < (op16 & 0xff)) { + ++uip_acc32[2]; + if(uip_acc32[2] == 0) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; } } } } /*-----------------------------------------------------------------------------------*/ -void -uip_add_ack_nxt(u16_t n) -{ - uip_conn->ack_nxt[3] += (n & 0xff); - uip_conn->ack_nxt[2] += (n >> 8); - - if(uip_conn->ack_nxt[2] < (n >> 8)) { - ++uip_conn->ack_nxt[1]; - if(uip_conn->ack_nxt[1] == 0) { - ++uip_conn->ack_nxt[0]; - } - } - - - if(uip_conn->ack_nxt[3] < (n & 0xff)) { - ++uip_conn->ack_nxt[2]; - if(uip_conn->ack_nxt[2] == 0) { - ++uip_conn->ack_nxt[1]; - if(uip_conn->ack_nxt[1] == 0) { - ++uip_conn->ack_nxt[0]; - } - } - } -} -/*-----------------------------------------------------------------------------------*/ -#else /* UIP_BUFSIZE > 255 */ -/*-----------------------------------------------------------------------------------*/ -void -uip_add_rcv_nxt(u8_t n) -{ - uip_conn->rcv_nxt[3] += n; - if(uip_conn->rcv_nxt[3] < n) { - ++uip_conn->rcv_nxt[2]; - if(uip_conn->rcv_nxt[2] == 0) { - ++uip_conn->rcv_nxt[1]; - if(uip_conn->rcv_nxt[1] == 0) { - ++uip_conn->rcv_nxt[0]; - } - } - } -} -/*-----------------------------------------------------------------------------------*/ -void -uip_add_ack_nxt(u8_t n) -{ - uip_conn->ack_nxt[3] += n; - if(uip_conn->ack_nxt[3] < n) { - ++uip_conn->ack_nxt[2]; - if(uip_conn->ack_nxt[2] == 0) { - ++uip_conn->ack_nxt[1]; - if(uip_conn->ack_nxt[1] == 0) { - ++uip_conn->ack_nxt[0]; - } - } - } -} -/*-----------------------------------------------------------------------------------*/ -#endif /* UIP_BUFSIZE > 255 */ -static u16_t -chksum(u16_t *sdata, u16_t len) +u16_t +uip_chksum(u16_t *sdata, u16_t len) { u16_t acc; @@ -157,7 +97,7 @@ chksum(u16_t *sdata, u16_t len) u16_t uip_ipchksum(void) { - return chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); + return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); } /*-----------------------------------------------------------------------------------*/ u16_t @@ -167,12 +107,12 @@ uip_tcpchksum(void) /* Compute the checksum of the TCP header. */ - hsum = chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); + hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); /* Compute the checksum of the data in the TCP packet and add it to the TCP header checksum. */ - sum = chksum((u16_t *)uip_appdata, - (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); + sum = uip_chksum((u16_t *)uip_appdata, + (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); if((sum += hsum) < hsum) { ++sum; diff --git a/unix/uipopt.h b/unix/uipopt.h index bb0c857..bbf3ef0 100644 --- a/unix/uipopt.h +++ b/unix/uipopt.h @@ -1,5 +1,27 @@ +/** + * \defgroup uipopt Configuration options for uIP + * @{ + * + * uIP is configured using the per-project configuration file + * "uipopt.h". This file contains all compile-time options for uIP and + * should be tweaked to match each specific project. The uIP + * distribution contains a documented example "uipopt.h" that can be + * copied and modified for each project. + */ + +/** + * \file + * Configuration options for uIP. + * \author Adam Dunkels + * + * This file is used for tweaking various configuration options for + * uIP. You should make a copy of this file into one of your project's + * directories instead of editing this example "uipopt.h" file that + * comes with the uIP distribution. + */ + /* - * Copyright (c) 2001, Adam Dunkels. + * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +32,7 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Dunkels. - * 4. The name of the author may not be used to endorse or promote + * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * @@ -31,149 +50,433 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uipopt.h,v 1.5 2002/01/13 21:12:41 adam Exp $ + * $Id: uipopt.h,v 1.16.2.5 2003/10/07 13:22:51 adam Exp $ * */ #ifndef __UIPOPT_H__ #define __UIPOPT_H__ -/* This file is used for tweaking various configuration options for - uIP. You should make a copy of this file into one of your project's - directories instead of editing this example "uipopt.h" file that - comes with the uIP distribution. */ +/*------------------------------------------------------------------------------*/ +/** + * \defgroup uipopttypedef uIP type definitions + * @{ + */ -/*-----------------------------------------------------------------------------------*/ -/* First, two typedefs that may have to be tweaked for your particular - compiler. The uX_t types are unsigned integer types, where the X is - the number of bits in the integer type. Most compilers use - "unsigned char" and "unsigned short" for those two, - respectively. */ +/** + * The 8-bit unsigned data type. + * + * This may have to be tweaked for your particular compiler. "unsigned + * char" works for most compilers. + */ typedef unsigned char u8_t; + +/** + * The 16-bit unsigned data type. + * + * This may have to be tweaked for your particular compiler. "unsigned + * short" works for most compilers. + */ typedef unsigned short u16_t; -/*-----------------------------------------------------------------------------------*/ -/* The configuration options for a specific node. This includes IP - * address, netmask and default router as well as the Ethernet - * address. The netmask, default router and Ethernet address are - * appliciable only if uIP should be run over Ethernet. +/** + * The statistics data type. + * + * This datatype determines how high the statistics counters are able + * to count. + */ +typedef unsigned short uip_stats_t; + +/** @} */ + +/*------------------------------------------------------------------------------*/ + +/** + * \defgroup uipoptstaticconf Static configuration options + * @{ + * + * These configuration options can be used for setting the IP address + * settings statically, but only if UIP_FIXEDADDR is set to 1. The + * configuration options for a specific node includes IP address, + * netmask and default router as well as the Ethernet address. The + * netmask, default router and Ethernet address are appliciable only + * if uIP should be run over Ethernet. * * All of these should be changed to suit your project. */ -/* UIP_IPADDR: The IP address of this uIP node. */ -#define UIP_IPADDR0 192 -#define UIP_IPADDR1 168 -#define UIP_IPADDR2 0 -#define UIP_IPADDR3 2 - -/* UIP_NETMASK: The netmask. */ -#define UIP_NETMASK0 255 -#define UIP_NETMASK1 255 -#define UIP_NETMASK2 255 -#define UIP_NETMASK3 0 - -/* UIP_DRIPADDR: IP address of the default router. */ -#define UIP_DRIPADDR0 192 -#define UIP_DRIPADDR1 168 -#define UIP_DRIPADDR2 0 -#define UIP_DRIPADDR3 1 - -/* UIP_ETHADDR: The Ethernet address. */ -#define UIP_ETHADDR0 0x00 -#define UIP_ETHADDR1 0xbd -#define UIP_ETHADDR2 0x3b -#define UIP_ETHADDR3 0x33 -#define UIP_ETHADDR4 0x05 -#define UIP_ETHADDR5 0x71 - - -/*-----------------------------------------------------------------------------------*/ -/* The following options are used to configure application specific - * setting such as how many TCP ports that should be avaliable and if - * the uIP should be configured to support active opens. +/** + * Determines if uIP should use a fixed IP address or not. * - * These should probably be tweaked to suite your project. + * If uIP should use a fixed IP address, the settings are set in the + * uipopt.h file. If not, the macros uip_sethostaddr(), + * uip_setdraddr() and uip_setnetmask() should be used instead. + * + * \hideinitializer */ +#define UIP_FIXEDADDR 1 -/* Include the header file for the application program that should be - used. If you don't use the example web server, you should change - this. */ -#include "httpd.h" - -/* UIP_ACTIVE_OPEN: Determines if support for opening connections from - uIP should be compiled in. If this isn't needed for your - application, don't turn it on. (A web server doesn't need this, for - instance.) */ -#define UIP_ACTIVE_OPEN 0 - -/* UIP_CONNS: The maximum number of simultaneously active - connections. */ -#define UIP_CONNS 10 - -/* UIP_LISTENPORTS: The maximum number of simultaneously listening TCP - ports. For a web server, 1 is enough here. */ -#define UIP_LISTENPORTS 10 - -/* UIP_BUFSIZE: The size of the buffer that holds incoming and - outgoing packets. */ -#define UIP_BUFSIZE 180 - -/* UIP_STATISTICS: Determines if statistics support should be compiled - in. The statistics is useful for debugging and to show the user. */ -#define UIP_STATISTICS 0 - -/* UIP_LOGGING: Determines if logging of certain events should be - compiled in. Useful mostly for debugging. The function uip_log(char - *msg) must be implemented to suit your architecture if logging is - turned on. */ -#define UIP_LOGGING 0 - -/* UIP_LLH_LEN: The link level header length; this is the offset into - the uip_buf where the IP header can be found. For Ethernet, this - should be set to 14. For SLIP, this should be set to 0. */ -#define UIP_LLH_LEN 14 - -/*-----------------------------------------------------------------------------------*/ -/* The following configuration options can be tweaked for your - * project, but you are probably safe to use the default values. The - * options are listed in order of tweakability. +/** + * Ping IP address asignment. + * + * uIP uses a "ping" packets for setting its own IP address if this + * option is set. If so, uIP will start with an empty IP address and + * the destination IP address of the first incoming "ping" (ICMP echo) + * packet will be used for setting the hosts IP address. + * + * \note This works only if UIP_FIXEDADDR is 0. + * + * \hideinitializer */ +#define UIP_PINGADDRCONF 0 -/* UIP_ARPTAB_SIZE: The size of the ARP table - use a larger value if - this uIP node will have many connections from the local network. */ -#define UIP_ARPTAB_SIZE 8 +#define UIP_IPADDR0 192 /**< The first octet of the IP address of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_IPADDR1 168 /**< The second octet of the IP address of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_IPADDR2 0 /**< The third octet of the IP address of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_IPADDR3 2 /**< The fourth octet of the IP address of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ -/* The maxium age of ARP table entries measured in 10ths of - seconds. An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD - default). */ -#define UIP_ARP_MAXAGE 120 +#define UIP_NETMASK0 255 /**< The first octet of the netmask of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_NETMASK1 255 /**< The second octet of the netmask of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_NETMASK2 255 /**< The third octet of the netmask of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of + this uIP node, if UIP_FIXEDADDR is + 1. \hideinitializer */ -/* UIP_RTO: The retransmission timeout counted in timer pulses (i.e., - the speed of the periodic timer, usually one second). */ -#define UIP_RTO 3 +#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of + the default router, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of + the default router, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of + the default router, if UIP_FIXEDADDR is + 1. \hideinitializer */ +#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of + the default router, if UIP_FIXEDADDR is + 1. \hideinitializer */ -/* UIP_MAXRTX: The maximum number of times a segment should be - retransmitted before the connection should be aborted. */ -#define UIP_MAXRTX 8 +/** + * Specifies if the uIP ARP module should be compiled with a fixed + * Ethernet MAC address or not. + * + * If this configuration option is 0, the macro uip_setethaddr() can + * be used to specify the Ethernet address at run-time. + * + * \hideinitializer + */ +#define UIP_FIXEDETHADDR 0 -/* UIP_TCP_MSS: The TCP maximum segment size. This should be set to - at most UIP_BUFSIZE - UIP_LLH_LEN - 40. */ -#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40) +#define UIP_ETHADDR0 0x00 /**< The first octet of the Ethernet + address if UIP_FIXEDETHADDR is + 1. \hideinitializer */ +#define UIP_ETHADDR1 0xbd /**< The second octet of the Ethernet + address if UIP_FIXEDETHADDR is + 1. \hideinitializer */ +#define UIP_ETHADDR2 0x3b /**< The third octet of the Ethernet + address if UIP_FIXEDETHADDR is + 1. \hideinitializer */ +#define UIP_ETHADDR3 0x33 /**< The fourth octet of the Ethernet + address if UIP_FIXEDETHADDR is + 1. \hideinitializer */ +#define UIP_ETHADDR4 0x05 /**< The fifth octet of the Ethernet + address if UIP_FIXEDETHADDR is + 1. \hideinitializer */ +#define UIP_ETHADDR5 0x71 /**< The sixth octet of the Ethernet + address if UIP_FIXEDETHADDR is + 1. \hideinitializer */ -/* UIP_TTL: The IP TTL (time to live) of IP packets sent by uIP. */ +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \defgroup uipoptip IP configuration options + * @{ + * + */ +/** + * The IP TTL (time to live) of IP packets sent by uIP. + * + * This should normally not be changed. + */ #define UIP_TTL 255 -/* UIP_TIME_WAIT_TIMEOUT: How long a connection should stay in the - TIME_WAIT state. Has no real implication, so it should be left - untouched. */ +/** + * Turn on support for IP packet reassembly. + * + * uIP supports reassembly of fragmented IP packets. This features + * requires an additonal amount of RAM to hold the reassembly buffer + * and the reassembly code size is approximately 700 bytes. The + * reassembly buffer is of the same size as the uip_buf buffer + * (configured by UIP_BUFSIZE). + * + * \note IP packet reassembly is not heavily tested. + * + * \hideinitializer + */ +#define UIP_REASSEMBLY 0 + +/** + * The maximum time an IP fragment should wait in the reassembly + * buffer before it is dropped. + * + */ +#define UIP_REASS_MAXAGE 40 + +/** @} */ + +/*------------------------------------------------------------------------------*/ +/** + * \defgroup uipoptudp UDP configuration options + * @{ + * + * \note The UDP support in uIP is still not entirely complete; there + * is no support for sending or receiving broadcast or multicast + * packets, but it works well enough to support a number of vital + * applications such as DNS queries, though + */ + +/** + * Toggles wether UDP support should be compiled in or not. + * + * \hideinitializer + */ +#define UIP_UDP 0 + +/** + * Toggles if UDP checksums should be used or not. + * + * \note Support for UDP checksums is currently not included in uIP, + * so this option has no function. + * + * \hideinitializer + */ +#define UIP_UDP_CHECKSUMS 0 + +/** + * The maximum amount of concurrent UDP connections. + * + * \hideinitializer + */ +#define UIP_UDP_CONNS 10 + +/** + * The name of the function that should be called when UDP datagrams arrive. + * + * \hideinitializer + */ +#define UIP_UDP_APPCALL udp_appcall + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \defgroup uipopttcp TCP configuration options + * @{ + */ + +/** + * Determines if support for opening connections from uIP should be + * compiled in. + * + * If the applications that are running on top of uIP for this project + * do not need to open outgoing TCP connections, this configration + * option can be turned off to reduce the code size of uIP. + * + * \hideinitializer + */ +#define UIP_ACTIVE_OPEN 1 + +/** + * The maximum number of simultaneously open TCP connections. + * + * Since the TCP connections are statically allocated, turning this + * configuration knob down results in less RAM used. Each TCP + * connection requires approximatly 30 bytes of memory. + * + * \hideinitializer + */ +#define UIP_CONNS 10 + +/** + * The maximum number of simultaneously listening TCP ports. + * + * Each listening TCP port requires 2 bytes of memory. + * + * \hideinitializer + */ +#define UIP_LISTENPORTS 10 + +/** + * The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the uip_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + * + * \hideinitializer + */ +#define UIP_RECEIVE_WINDOW 32768 + +/** + * Determines if support for TCP urgent data notification should be + * compiled in. + * + * Urgent data (out-of-band data) is a rarely used TCP feature that + * very seldom would be required. + * + * \hideinitializer + */ +#define UIP_URGDATA 1 + +/** + * The initial retransmission timeout counted in timer pulses. + * + * This should not be changed. + */ +#define UIP_RTO 3 + +/** + * The maximum number of times a segment should be retransmitted + * before the connection should be aborted. + * + * This should not be changed. + */ +#define UIP_MAXRTX 8 + +/** + * The maximum number of times a SYN segment should be retransmitted + * before a connection request should be deemed to have been + * unsuccessful. + * + * This should not need to be changed. + */ +#define UIP_MAXSYNRTX 3 + +/** + * The TCP maximum segment size. + * + * This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40. + */ +#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40) + +/** + * How long a connection should stay in the TIME_WAIT state. + * + * This configiration option has no real implication, and it should be + * left untouched. + */ #define UIP_TIME_WAIT_TIMEOUT 120 -/*-----------------------------------------------------------------------------------*/ -/* This is where you configure if your CPU architecture is big or - * little endian. Most CPUs today are little endian. The most notable - * exception are the Motorolas which are big endian. Tweak the - * definition of the BYTE_ORDER macro to configure uIP for your - * project. + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \defgroup uipoptarp ARP configuration options + * @{ + */ + +/** + * The size of the ARP table. + * + * This option should be set to a larger value if this uIP node will + * have many connections from the local network. + * + * \hideinitializer + */ +#define UIP_ARPTAB_SIZE 8 + +/** + * The maxium age of ARP table entries measured in 10ths of seconds. + * + * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD + * default). + */ +#define UIP_ARP_MAXAGE 120 + +/** @} */ + +/*------------------------------------------------------------------------------*/ + +/** + * \defgroup uipoptgeneral General configuration options + * @{ + */ + +/** + * The size of the uIP packet buffer. + * + * The uIP packet buffer should not be smaller than 60 bytes, and does + * not need to be larger than 1500 bytes. Lower size results in lower + * TCP throughput, larger size results in higher TCP throughput. + * + * \hideinitializer + */ +#define UIP_BUFSIZE 1500 + + +/** + * Determines if statistics support should be compiled in. + * + * The statistics is useful for debugging and to show the user. + * + * \hideinitializer + */ +#define UIP_STATISTICS 1 + +/** + * Determines if logging of certain events should be compiled in. + * + * This is useful mostly for debugging. The function uip_log() + * must be implemented to suit the architecture of the project, if + * logging is turned on. + * + * \hideinitializer + */ +#define UIP_LOGGING 0 + +/** + * Print out a uIP log message. + * + * This function must be implemented by the module that uses uIP, and + * is called by uIP whenever a log message is generated. + */ +void uip_log(char *msg); + +/** + * The link level header length. + * + * This is the offset into the uip_buf where the IP header can be + * found. For Ethernet, this should be set to 14. For SLIP, this + * should be set to 0. + * + * \hideinitializer + */ +#define UIP_LLH_LEN 14 + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \defgroup uipoptcpu CPU architecture configuration + * @{ + * + * The CPU architecture configuration is where the endianess of the + * CPU on which uIP is to be run is specified. Most CPUs today are + * little endian, and the most notable exception are the Motorolas + * which are big endian. The BYTE_ORDER macro should be changed to + * reflect the CPU architecture on which uIP is to be run. */ #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN 3412 @@ -182,8 +485,73 @@ typedef unsigned short u16_t; #define BIG_ENDIAN 1234 #endif /* BIGE_ENDIAN */ +/** + * The byte order of the CPU architecture on which uIP is to be run. + * + * This option can be either BIG_ENDIAN (Motorola byte order) or + * LITTLE_ENDIAN (Intel byte order). + * + * \hideinitializer + */ #ifndef BYTE_ORDER #define BYTE_ORDER LITTLE_ENDIAN #endif /* BYTE_ORDER */ +/** @} */ +/*------------------------------------------------------------------------------*/ + +/** + * \defgroup uipoptapp Appication specific configurations + * @{ + * + * An uIP application is implemented using a single application + * function that is called by uIP whenever a TCP/IP event occurs. The + * name of this function must be registered with uIP at compile time + * using the UIP_APPCALL definition. + * + * uIP applications can store the application state within the + * uip_conn structure by specifying the size of the application + * structure with the UIP_APPSTATE_SIZE macro. + * + * The file containing the definitions must be included in the + * uipopt.h file. + * + * The following example illustrates how this can look. + \code + +void httpd_appcall(void); +#define UIP_APPCALL httpd_appcall + +struct httpd_state { + u8_t state; + u16_t count; + char *dataptr; + char *script; +}; +#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) + \endcode + */ + +/** + * \var #define UIP_APPCALL + * + * The name of the application function that uIP should call in + * response to TCP/IP events. + * + */ + +/** + * \var #define UIP_APPSTATE_SIZE + * + * The size of the application state that is to be stored in the + * uip_conn structure. + */ +/** @} */ + +/* Include the header file for the application program that should be + used. If you don't use the example web server, you should change + this. */ +#include "httpd.h" + + #endif /* __UIPOPT_H__ */