summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-11-19 23:09:39 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-11-19 23:09:39 +0000
commit0cc9b5ef69aa200c2610f3e87281fe9aa9d7d389 (patch)
tree3b0f4ca1b8066bdd68f41c4640f074c9b5535ffa
parentbefc37ada0b901ad7c315e4089976508396d496b (diff)
downloadnuttx-0cc9b5ef69aa200c2610f3e87281fe9aa9d7d389.tar.gz
nuttx-0cc9b5ef69aa200c2610f3e87281fe9aa9d7d389.tar.bz2
nuttx-0cc9b5ef69aa200c2610f3e87281fe9aa9d7d389.zip
Add TCP readahead logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@387 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog1
-rw-r--r--nuttx/Documentation/NuttX.html1
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html10
-rw-r--r--nuttx/arch/arm/src/common/up_sigdeliver.c2
-rw-r--r--nuttx/arch/sim/src/up_tapdev.c6
-rw-r--r--nuttx/arch/sim/src/up_uipdriver.c2
-rw-r--r--nuttx/configs/README.txt7
-rw-r--r--nuttx/configs/c5471evm/defconfig10
-rw-r--r--nuttx/configs/m68332evb/defconfig10
-rw-r--r--nuttx/configs/mcu123-lpc214x/defconfig10
-rw-r--r--nuttx/configs/ntosd-dm320/defconfig10
-rw-r--r--nuttx/configs/ntosd-dm320/netconfig10
-rw-r--r--nuttx/configs/pjrc-8051/defconfig10
-rw-r--r--nuttx/configs/sim/defconfig10
-rw-r--r--nuttx/configs/sim/netconfig10
-rw-r--r--nuttx/drivers/net/dm90x0.c2
-rw-r--r--nuttx/examples/nettest/nettest-server.c11
-rw-r--r--nuttx/include/net/uip/uip-arch.h2
-rw-r--r--nuttx/include/net/uip/uip-lib.h4
-rw-r--r--nuttx/include/net/uip/uip.h42
-rw-r--r--nuttx/include/net/uip/uipopt.h130
-rw-r--r--nuttx/net/netdev-ioctl.c2
-rw-r--r--nuttx/net/recvfrom.c143
-rw-r--r--nuttx/net/socket.c5
-rw-r--r--nuttx/net/uip/Make.defs3
-rw-r--r--nuttx/net/uip/uip-arp.c18
-rw-r--r--nuttx/net/uip/uip-chksum.c2
-rw-r--r--nuttx/net/uip/uip-fw.c230
-rw-r--r--nuttx/net/uip/uip-icmpinput.c4
-rw-r--r--nuttx/net/uip/uip-initialize.c6
-rw-r--r--nuttx/net/uip/uip-input.c10
-rw-r--r--nuttx/net/uip/uip-internal.h8
-rw-r--r--nuttx/net/uip/uip-listen.c10
-rw-r--r--nuttx/net/uip/uip-send.c2
-rw-r--r--nuttx/net/uip/uip-setipid.c2
-rw-r--r--nuttx/net/uip/uip-split.c132
-rw-r--r--nuttx/net/uip/uip-tcpcallback.c103
-rw-r--r--nuttx/net/uip/uip-tcpconn.c20
-rw-r--r--nuttx/net/uip/uip-tcpinput.c2
-rw-r--r--nuttx/net/uip/uip-tcpreadahead.c132
-rw-r--r--nuttx/net/uip/uip-tcpsend.c4
-rw-r--r--nuttx/net/uip/uip-udpconn.c6
-rw-r--r--nuttx/net/uip/uip-udpsend.c2
-rw-r--r--nuttx/netutils/uiplib/uip-server.c39
-rw-r--r--nuttx/netutils/webserver/httpd-cgi.c2
-rw-r--r--nuttx/netutils/webserver/httpd.c120
-rw-r--r--nuttx/sched/task_create.c2
47 files changed, 853 insertions, 456 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index daf3551d7..6422f9997 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -226,4 +226,5 @@
* Basic server functionality verified: listen(), accept()
* Fix DM90x0 driver problem that caused TX overruns
* Add strncmp()
+ * Added TCP/IP read-ahead buffer to minimize failed ACKs and packet loss.
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index 8fa4cc0ad..ce7ebbcc6 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -683,6 +683,7 @@ Other memory:
* Basic server functionality verified: listen(), accept()
* Fix DM90x0 driver problem that caused TX overruns
* Add strncmp()
+ * Added TCP/IP read-ahead buffer to minimize failed ACKs and packet loss.
</pre></ul>
<table width ="100%">
diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html
index 923f08e84..faf3c5f89 100644
--- a/nuttx/Documentation/NuttxPortingGuide.html
+++ b/nuttx/Documentation/NuttxPortingGuide.html
@@ -1353,7 +1353,7 @@ The system can be re-made subsequently by just typing <code>make</code>.
<code>CONFIG_NSOCKET_DESCRIPTORS</code>: Maximum number of socket descriptors per task/thread.
</li>
<li>
- <code>CONFIG_NET_MAX_CONNECTIONS</code>: Maximum number of TCP connections (all tasks).
+ <code>CONFIG_NET_TCP_CONNS</code>: Maximum number of TCP connections (all tasks).
</li>
<li>
<code>CONFIG_NET_MAX_LISTENPORTS</code>: Maximum number of listening TCP ports (all tasks).
@@ -1362,7 +1362,13 @@ The system can be re-made subsequently by just typing <code>make</code>.
<code>CONFIG_NET_SOCKOPTS</code>: Enable or disable support for socket options.
</li>
<li>
- <code>CONFIG_NET_BUFFER_SIZE</code>: uIP buffer size
+ <code>CONFIG_NET_BUFSIZE</code>: uIP buffer size
+ </li>
+ <li>
+ <code>CONFIG_NET_TCP_READAHEAD_BUFSIZE</code>: Size of TCP read-ahead buffers
+ </li>
+ <li>
+ <code>CONFIG_NET_NTCP_READAHEAD_BUFFERS</code>: Number of TCP read-ahead buffers (may be zero)
</li>
<li>
<code>CONFIG_NET_UDP</code>: UDP support on or off
diff --git a/nuttx/arch/arm/src/common/up_sigdeliver.c b/nuttx/arch/arm/src/common/up_sigdeliver.c
index e6a0dfd89..673855144 100644
--- a/nuttx/arch/arm/src/common/up_sigdeliver.c
+++ b/nuttx/arch/arm/src/common/up_sigdeliver.c
@@ -76,6 +76,7 @@
void up_sigdeliver(void)
{
+#ifndef CONFIG_DISABLE_SIGNALS
_TCB *rtcb = (_TCB*)g_readytorun.head;
uint32 regs[XCPTCONTEXT_REGS];
sig_deliver_t sigdeliver;
@@ -132,4 +133,5 @@ void up_sigdeliver(void)
up_ledoff(LED_SIGNAL);
up_fullcontextrestore(regs);
+#endif
}
diff --git a/nuttx/arch/sim/src/up_tapdev.c b/nuttx/arch/sim/src/up_tapdev.c
index a649c2490..7e9809e5c 100644
--- a/nuttx/arch/sim/src/up_tapdev.c
+++ b/nuttx/arch/sim/src/up_tapdev.c
@@ -217,10 +217,10 @@ static inline void dump_ethhdr(const char *msg, unsigned char *buf, int buflen)
lib_rawprintf(" %02x:%02x:%02x:%02x:%02x:%02x %02x:%02x:%02x:%02x:%02x:%02x %02x%02x\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
-#if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN
- buf[12], buf[13]);
-#else
+#ifdef CONFIG_ENDIAN_BIG
buf[13], buf[12]);
+#else
+ buf[12], buf[13]);
#endif
}
#else
diff --git a/nuttx/arch/sim/src/up_uipdriver.c b/nuttx/arch/sim/src/up_uipdriver.c
index d7425f82f..dbc78f9c0 100644
--- a/nuttx/arch/sim/src/up_uipdriver.c
+++ b/nuttx/arch/sim/src/up_uipdriver.c
@@ -141,7 +141,7 @@ void uipdriver_loop(void)
/* tapdev_read will return 0 on a timeout event and >0 on a data received event */
- g_sim_dev.d_len = tapdev_read((unsigned char*)g_sim_dev.d_buf, UIP_BUFSIZE);
+ g_sim_dev.d_len = tapdev_read((unsigned char*)g_sim_dev.d_buf, CONFIG_NET_BUFSIZE);
/* Disable preemption through to the following so that it behaves a little more
* like an interrupt (otherwise, the following logic gets pre-empted an behaves
diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt
index cc8643068..da9535e8a 100644
--- a/nuttx/configs/README.txt
+++ b/nuttx/configs/README.txt
@@ -213,11 +213,14 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_NET_IPv6 - Build in support for IPv6
CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors
per task/thread.
- CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+ CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
- CONFIG_NET_BUFFER_SIZE - uIP buffer size
+ CONFIG_NET_BUFSIZE - uIP buffer size
+ CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+ CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers
+ (may be zero)
CONFIG_NET_UDP - UDP support on or off
CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP
diff --git a/nuttx/configs/c5471evm/defconfig b/nuttx/configs/c5471evm/defconfig
index db582e93b..2bc085041 100644
--- a/nuttx/configs/c5471evm/defconfig
+++ b/nuttx/configs/c5471evm/defconfig
@@ -254,10 +254,12 @@ CONFIG_PREALLOC_TIMERS=8
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -271,10 +273,10 @@ CONFIG_PREALLOC_TIMERS=8
CONFIG_NET=n
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=0
-CONFIG_NET_MAX_CONNECTIONS=40
+CONFIG_NET_TCP_CONNS=40
CONFIG_NET_MAX_LISTENPORTS=40
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=n
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/configs/m68332evb/defconfig b/nuttx/configs/m68332evb/defconfig
index 700bcbb0f..b07ac62a0 100644
--- a/nuttx/configs/m68332evb/defconfig
+++ b/nuttx/configs/m68332evb/defconfig
@@ -243,10 +243,12 @@ CONFIG_PREALLOC_TIMERS=8
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -260,10 +262,10 @@ CONFIG_PREALLOC_TIMERS=8
CONFIG_NET=n
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=0
-CONFIG_NET_MAX_CONNECTIONS=40
+CONFIG_NET_TCP_CONNS=40
CONFIG_NET_MAX_LISTENPORTS=40
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=n
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/configs/mcu123-lpc214x/defconfig b/nuttx/configs/mcu123-lpc214x/defconfig
index aa6352420..fe6a93801 100644
--- a/nuttx/configs/mcu123-lpc214x/defconfig
+++ b/nuttx/configs/mcu123-lpc214x/defconfig
@@ -267,10 +267,12 @@ CONFIG_PREALLOC_TIMERS=8
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -284,10 +286,10 @@ CONFIG_PREALLOC_TIMERS=8
CONFIG_NET=n
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=0
-CONFIG_NET_MAX_CONNECTIONS=40
+CONFIG_NET_TCP_CONNS=40
CONFIG_NET_MAX_LISTENPORTS=40
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=n
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/configs/ntosd-dm320/defconfig b/nuttx/configs/ntosd-dm320/defconfig
index b3576fd5a..d7ae85b3b 100644
--- a/nuttx/configs/ntosd-dm320/defconfig
+++ b/nuttx/configs/ntosd-dm320/defconfig
@@ -252,10 +252,12 @@ CONFIG_PREALLOC_TIMERS=8
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -269,10 +271,10 @@ CONFIG_PREALLOC_TIMERS=8
CONFIG_NET=n
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=0
-CONFIG_NET_MAX_CONNECTIONS=40
+CONFIG_NET_TCP_CONNS=40
CONFIG_NET_MAX_LISTENPORTS=40
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=n
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/configs/ntosd-dm320/netconfig b/nuttx/configs/ntosd-dm320/netconfig
index 050196ee5..042a49077 100644
--- a/nuttx/configs/ntosd-dm320/netconfig
+++ b/nuttx/configs/ntosd-dm320/netconfig
@@ -253,10 +253,12 @@ CONFIG_PREALLOC_TIMERS=8
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -270,10 +272,10 @@ CONFIG_PREALLOC_TIMERS=8
CONFIG_NET=y
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=8
-CONFIG_NET_MAX_CONNECTIONS=8
+CONFIG_NET_TCP_CONNS=8
CONFIG_NET_MAX_LISTENPORTS=8
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=y
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/configs/pjrc-8051/defconfig b/nuttx/configs/pjrc-8051/defconfig
index 61ad5c12c..d3abb4e9d 100644
--- a/nuttx/configs/pjrc-8051/defconfig
+++ b/nuttx/configs/pjrc-8051/defconfig
@@ -240,10 +240,12 @@ CONFIG_PREALLOC_TIMERS=0
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -257,10 +259,10 @@ CONFIG_PREALLOC_TIMERS=0
CONFIG_NET=n
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=0
-CONFIG_NET_MAX_CONNECTIONS=40
+CONFIG_NET_TCP_CONNS=40
CONFIG_NET_MAX_LISTENPORTS=40
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=n
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/configs/sim/defconfig b/nuttx/configs/sim/defconfig
index 2d959fbcf..45b338948 100644
--- a/nuttx/configs/sim/defconfig
+++ b/nuttx/configs/sim/defconfig
@@ -214,10 +214,12 @@ CONFIG_FS_FAT=y
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -231,10 +233,10 @@ CONFIG_FS_FAT=y
CONFIG_NET=n
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=0
-CONFIG_NET_MAX_CONNECTIONS=40
+CONFIG_NET_TCP_CONNS=40
CONFIG_NET_MAX_LISTENPORTS=40
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=n
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/configs/sim/netconfig b/nuttx/configs/sim/netconfig
index 2cdea0a61..781a4d8c0 100644
--- a/nuttx/configs/sim/netconfig
+++ b/nuttx/configs/sim/netconfig
@@ -215,10 +215,12 @@ CONFIG_FS_FAT=y
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
-# CONFIG_NET_MAX_CONNECTIONS - Maximum number of TCP connections (all tasks)
+# CONFIG_NET_TCP_CONNS - Maximum number of TCP connections (all tasks)
# CONFIG_NET_MAX_LISTENPORTS - Maximum number of listening TCP ports (all tasks)
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
-# CONFIG_NET_BUFFER_SIZE - uIP buffer size
+# CONFIG_NET_BUFSIZE - uIP buffer size
+# CONFIG_NET_TCP_READAHEAD_BUFSIZE - Size of TCP read-ahead buffers
+# CONFIG_NET_NTCP_READAHEAD_BUFFERS - Number of TCP read-ahead buffers (may be zero)
# CONFIG_NET_UDP - UDP support on or off
# CONFIG_NET_UDP_CHECKSUMS - UDP checksums on or off
# CONFIG_NET_UDP_CONNS - The maximum amount of concurrent UDP connections
@@ -232,10 +234,10 @@ CONFIG_FS_FAT=y
CONFIG_NET=y
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=8
-CONFIG_NET_MAX_CONNECTIONS=40
+CONFIG_NET_TCP_CONNS=40
CONFIG_NET_MAX_LISTENPORTS=40
CONFIG_NET_SOCKOPTS=y
-CONFIG_NET_BUFFER_SIZE=420
+CONFIG_NET_BUFSIZE=420
CONFIG_NET_UDP=y
CONFIG_NET_UDP_CHECKSUMS=y
#CONFIG_NET_UDP_CONNS=10
diff --git a/nuttx/drivers/net/dm90x0.c b/nuttx/drivers/net/dm90x0.c
index 0df832e8f..a604b65a3 100644
--- a/nuttx/drivers/net/dm90x0.c
+++ b/nuttx/drivers/net/dm90x0.c
@@ -958,7 +958,7 @@ static void dm9x_receive(struct dm9x_driver_s *dm9x)
/* Also check if the packet is a valid size for the uIP configuration */
- else if (rx.desc.rx_len < UIP_LLH_LEN || rx.desc.rx_len > (UIP_BUFSIZE + 2))
+ else if (rx.desc.rx_len < UIP_LLH_LEN || rx.desc.rx_len > (CONFIG_NET_BUFSIZE + 2))
{
#if defined(CONFIG_DM9X_STATS)
dm9x->dm_nrxlengtherrors++;
diff --git a/nuttx/examples/nettest/nettest-server.c b/nuttx/examples/nettest/nettest-server.c
index 984dee6b3..354f0560a 100644
--- a/nuttx/examples/nettest/nettest-server.c
+++ b/nuttx/examples/nettest/nettest-server.c
@@ -194,17 +194,6 @@ void recv_server(void)
}
}
-#ifdef CONFIG_EXAMPLE_NETTEST_HOST
- /* At present, data received by the target before it is completed the
- * the write opertion and started the read operation results in a failure
- * (the data is not received, but it is ACKed). This will have to be
- * fixed.
- */
-
-# warning "FIXME: This should not be necessary"
- sleep(10);
-#endif
-
/* Then send the same data back to the client */
message("server: Sending %d bytes\n", totalbytesread);
diff --git a/nuttx/include/net/uip/uip-arch.h b/nuttx/include/net/uip/uip-arch.h
index 8d2b15d40..b4f21fb64 100644
--- a/nuttx/include/net/uip/uip-arch.h
+++ b/nuttx/include/net/uip/uip-arch.h
@@ -116,7 +116,7 @@ struct uip_driver_s
* }
*/
- uint8 d_buf[UIP_BUFSIZE + 2];
+ uint8 d_buf[CONFIG_NET_BUFSIZE + 2];
/* d_appdata points to the location where application data can be read from
* or written into a packet.
diff --git a/nuttx/include/net/uip/uip-lib.h b/nuttx/include/net/uip/uip-lib.h
index d5799ee56..307a6b277 100644
--- a/nuttx/include/net/uip/uip-lib.h
+++ b/nuttx/include/net/uip/uip-lib.h
@@ -47,7 +47,7 @@
****************************************************************************/
#include <nuttx/config.h>
-#include <sched.h>
+#include <pthread.h>
#include <netinet/in.h>
/****************************************************************************
@@ -106,6 +106,6 @@ extern int uip_setnetmask(const char *ifname, const struct in_addr *addr);
/* Generic server logic */
-extern void uip_server(uint16 portno, main_t handler, int stacksize);
+extern void uip_server(uint16 portno, pthread_startroutine_t handler, int stacksize);
#endif /* __UIPLIB_H__ */
diff --git a/nuttx/include/net/uip/uip.h b/nuttx/include/net/uip/uip.h
index 46e6907e4..150f594ce 100644
--- a/nuttx/include/net/uip/uip.h
+++ b/nuttx/include/net/uip/uip.h
@@ -112,7 +112,7 @@
* snprintf(dev->d_appdata, UIP_APPDATA_SIZE, "%u\n", i);
*/
-#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+#define UIP_APPDATA_SIZE (CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
#define UIP_PROTO_ICMP 1
#define UIP_PROTO_TCP 6
@@ -183,6 +183,12 @@ struct uip_conn
uint8 nrtx; /* The number of retransmissions for the last
* segment sent */
+ /* Read-ahead buffering */
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ sq_queue_t readahead;
+#endif
+
/* Higher level logic can retain application specific information
* in the following:
*
@@ -212,12 +218,27 @@ struct uip_conn
void (*connection_event)(struct uip_conn *conn, uint8 flags);
};
+/* The following structure is used to handle read-ahead buffering for TCP
+ * connection. When incoming TCP data is received while no application is
+ * listening for the data, that data will be retained in these read-ahead
+ * buffers so that no data is lost.
+ */
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+struct uip_readahead_s
+{
+ sq_entry_t rh_node; /* Supports a singly linked list */
+ uint16 rh_nbytes; /* Number of bytes available in this buffer */
+ uint8 rh_buffer[CONFIG_NET_TCP_READAHEAD_BUFSIZE];
+};
+#endif
+
#ifdef CONFIG_NET_UDP
/* Representation of a uIP UDP connection */
struct uip_udp_conn
{
- dq_entry_t node; /* Implements a doubly linked list */
+ dq_entry_t node; /* Supports a doubly linked list */
uip_ipaddr_t ripaddr; /* The IP address of the remote peer */
uint16 lport; /* The local port number in network byte order */
uint16 rport; /* The remote port number in network byte order */
@@ -493,11 +514,11 @@ extern struct uip_stats uip_stat;
* TCP/IP stack.
*/
-void uip_initialize(void);
+extern void uip_initialize(void);
/* This function may be used at boot time to set the initial ip_id.*/
-void uip_setipid(uint16 id);
+extern void uip_setipid(uint16 id);
/* uIP application functions
*
@@ -559,7 +580,7 @@ extern int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr)
* port A 16-bit port number in network byte order.
*/
-int uip_listen(uint16 port);
+extern int uip_listen(uint16 port);
/* Stop listening to the specified port.
*
@@ -569,7 +590,7 @@ int uip_listen(uint16 port);
* port A 16-bit port number in network byte order.
*/
-int uip_unlisten(uint16 port);
+extern int uip_unlisten(uint16 port);
/* Check if a connection has outstanding (i.e., unacknowledged) data */
@@ -598,7 +619,14 @@ int uip_unlisten(uint16 port);
* len The maximum amount of data bytes to be sent.
*/
-void uip_send(struct uip_driver_s *dev, const void *buf, int len);
+extern void uip_send(struct uip_driver_s *dev, const void *buf, int len);
+
+/* Access to TCP read-ahead buffers */
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+extern struct uip_readahead_s *uip_tcpreadaheadalloc(void);
+extern void uip_tcpreadaheadrelease(struct uip_readahead_s *buf);
+#endif /* CONFIG_NET_NTCP_READAHEAD_BUFFERS */
/* The length of any incoming data that is currently avaliable (if avaliable)
* in the d_appdata buffer.
diff --git a/nuttx/include/net/uip/uipopt.h b/nuttx/include/net/uip/uipopt.h
index 3a3fc68f2..b50884703 100644
--- a/nuttx/include/net/uip/uipopt.h
+++ b/nuttx/include/net/uip/uipopt.h
@@ -69,22 +69,6 @@
* Public Type Definitions
****************************************************************************/
-/* Static configuration options */
-
-/* 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.
- */
-
-#ifdef CONFIG_NET_PINGADDRCONF
-#define UIP_PINGADDRCONF CONFIG_NET_PINGADDRCONF
-#else /* CONFIG_NET_PINGADDRCONF */
-#define UIP_PINGADDRCONF 0
-#endif /* CONFIG_NET_PINGADDRCONF */
-
/* IP configuration options */
/* The IP TTL (time to live) of IP packets sent by uIP.
@@ -92,7 +76,7 @@
* This should normally not be changed.
*/
-#define UIP_TTL 64
+#define UIP_TTL 64
/* Turn on support for IP packet reassembly.
*
@@ -100,7 +84,7 @@
* 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 d_buf buffer
- * (configured by UIP_BUFSIZE).
+ * (configured by CONFIG_NET_BUFSIZE).
*
* Note: IP packet reassembly is not heavily tested.
*/
@@ -116,26 +100,12 @@
/* UDP configuration options */
-/* 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.
- */
+/* The maximum amount of concurrent UDP connection, Default: 10 */
-#ifdef CONFIG_NET_UDP_CHECKSUMS
-# define UIP_UDP_CHECKSUMS CONFIG_NET_UDP_CHECKSUMS
-#else
-# define UIP_UDP_CHECKSUMS 0
+#ifndef CONFIG_NET_UDP_CONNS
+# define CONFIG_NET_UDP_CONNS 10
#endif
-/* The maximum amount of concurrent UDP connections. */
-
-#ifdef CONFIG_NET_UDP_CONNS
-# define UIP_UDP_CONNS CONFIG_NET_UDP_CONNS
-#else /* CONFIG_NET_UDP_CONNS */
-# define UIP_UDP_CONNS 10
-#endif /* CONFIG_NET_UDP_CONNS */
-
/* TCP configuration options */
/* The maximum number of simultaneously open TCP connections.
@@ -145,11 +115,9 @@
* connection requires approximatly 30 bytes of memory.
*/
-#ifndef CONFIG_NET_MAX_CONNECTIONS
-# define UIP_CONNS 10
-#else /* CONFIG_NET_MAX_CONNECTIONS */
-# define UIP_CONNS CONFIG_NET_MAX_CONNECTIONS
-#endif /* CONFIG_NET_MAX_CONNECTIONS */
+#ifndef CONFIG_NET_TCP_CONNS
+# define CONFIG_NET_TCP_CONNS 10
+#endif
/* The maximum number of simultaneously listening TCP ports.
*
@@ -157,10 +125,8 @@
*/
#ifndef CONFIG_NET_MAX_LISTENPORTS
-# define UIP_LISTENPORTS 20
-#else /* CONFIG_NET_MAX_LISTENPORTS */
-# define UIP_LISTENPORTS CONFIG_NET_MAX_LISTENPORTS
-#endif /* CONFIG_NET_MAX_LISTENPORTS */
+# define CONFIG_NET_MAX_LISTENPORTS 20
+#endif
/* Determines if support for TCP urgent data notification should be
* compiled in.
@@ -169,14 +135,14 @@
* very seldom would be required.
*/
-#define UIP_URGDATA 0
+#define UIP_URGDATA 0
/* The initial retransmission timeout counted in timer pulses.
*
* This should not be changed.
*/
-#define UIP_RTO 3
+#define UIP_RTO 3
/* The maximum number of times a segment should be retransmitted
* before the connection should be aborted.
@@ -184,7 +150,7 @@
* This should not be changed.
*/
-#define UIP_MAXRTX 8
+#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
@@ -193,15 +159,15 @@
* This should not need to be changed.
*/
-#define UIP_MAXSYNRTX 5
+#define UIP_MAXSYNRTX 5
/* The TCP maximum segment size.
*
* This is should not be to set to more than
- * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
+ * CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
*/
-#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+#define UIP_TCP_MSS (CONFIG_NET_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
/* The size of the advertised receiver's window.
*
@@ -211,9 +177,7 @@
*/
#ifndef CONFIG_NET_RECEIVE_WINDOW
-# define UIP_RECEIVE_WINDOW UIP_TCP_MSS
-#else
-# define UIP_RECEIVE_WINDOW CONFIG_NET_RECEIVE_WINDOW
+# define CONFIG_NET_RECEIVE_WINDOW UIP_TCP_MSS
#endif
/* How long a connection should stay in the TIME_WAIT state.
@@ -232,10 +196,8 @@
* have many connections from the local network.
*/
-#ifdef CONFIG_NET_ARPTAB_SIZE
-# define UIP_ARPTAB_SIZE CONFIG_NET_ARPTAB_SIZE
-#else
-# define UIP_ARPTAB_SIZE 8
+#ifndef CONFIG_NET_ARPTAB_SIZE
+# define CONFIG_NET_ARPTAB_SIZE 8
#endif
/* The maxium age of ARP table entries measured in 10ths of seconds.
@@ -255,23 +217,21 @@
* TCP throughput, larger size results in higher TCP throughput.
*/
-#ifndef CONFIG_NET_BUFFER_SIZE
-# define UIP_BUFSIZE 400
-#else /* CONFIG_NET_BUFFER_SIZE */
-# define UIP_BUFSIZE CONFIG_NET_BUFFER_SIZE
-#endif /* CONFIG_NET_BUFFER_SIZE */
+#ifndef CONFIG_NET_BUFSIZE
+# define CONFIG_NET_BUFSIZE 400
+#endif
-/* Broadcast support.
- *
- * This flag configures IP broadcast support. This is useful only
- * together with UDP.
- */
+/* Number of TCP read-ahead buffers (may be zero) */
+
+#ifndef CONFIG_NET_NTCP_READAHEAD_BUFFERS
+# define CONFIG_NET_NTCP_READAHEAD_BUFFERS 4
+#endif
-#ifndef CONFIG_NET_BROADCAST
-# define UIP_BROADCAST 0
-#else /* CONFIG_NET_BROADCAST */
-# define UIP_BROADCAST CONFIG_NET_BROADCAST
-#endif /* CONFIG_NET_BROADCAST */
+/* The size of the TCP read buffer size */
+
+#ifndef CONFIG_NET_TCP_READAHEAD_BUFSIZE
+# define CONFIG_NET_TCP_READAHEAD_BUFSIZE UIP_TCP_MSS
+#endif
/* The link level header length.
*
@@ -282,32 +242,8 @@
#ifdef CONFIG_NET_LLH_LEN
# define UIP_LLH_LEN CONFIG_NET_LLH_LEN
-#else /* CONFIG_NET_LLH_LEN */
-# define UIP_LLH_LEN 14
-#endif /* CONFIG_NET_LLH_LEN */
-
-/* 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 CONFIG_ENDIAN_BIG macro should be changed
- * if uIP is to be run on a big endian architecture.
- */
-
-/* The byte order of the CPU architecture on which uIP is to be run.
- *
- * This option can be either CONFIG_ENDIAN_BIG (Motorola byte order) or
- * default little endian byte order (Intel byte order).
- */
-
-#define UIP_BIG_ENDIAN 1234
-#define UIP_LITTLE_ENDIAN 3412
-
-#ifdef CONFIG_ENDIAN_BIG
-# define UIP_BYTE_ORDER UIP_BIG_ENDIAN
#else
-# define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN
+# define UIP_LLH_LEN 14
#endif
/****************************************************************************
diff --git a/nuttx/net/netdev-ioctl.c b/nuttx/net/netdev-ioctl.c
index 3825a5f7b..e13a22170 100644
--- a/nuttx/net/netdev-ioctl.c
+++ b/nuttx/net/netdev-ioctl.c
@@ -215,7 +215,7 @@ int netdev_ioctl(int sockfd, int cmd, struct ifreq *req)
break;
case SIOCGIFMTU: /* Get MTU size */
- req->ifr_mtu = UIP_BUFSIZE;
+ req->ifr_mtu = CONFIG_NET_BUFSIZE;
break;
case SIOCGIFHWADDR: /* Get hardware address */
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index b0c9a223f..906b5aa6e 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -130,6 +130,93 @@ static void recvfrom_newdata(struct uip_driver_s *dev, struct recvfrom_s *pstate
}
/****************************************************************************
+ * Function: recvfrom_readahead
+ *
+ * Description:
+ * Copy the read data from the packet
+ *
+ * Parameters:
+ * dev The sructure of the network driver that caused the interrupt
+ * pstate recvfrom state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Running at the interrupt level
+ *
+ ****************************************************************************/
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+static inline void recvfrom_readahead(struct recvfrom_s *pstate)
+{
+ struct uip_conn *conn = (struct uip_conn *)pstate->rf_sock->s_conn;
+ struct uip_readahead_s *readahead;
+ size_t recvlen;
+
+ /* Check there is any TCP data already buffered in a read-ahead
+ * buffer.
+ */
+
+ do
+ {
+ /* Get the read-ahead buffer at the head of the list (if any) */
+
+ readahead = (struct uip_readahead_s *)sq_remfirst(&conn->readahead);
+ if (readahead)
+ {
+ /* We have a new buffer... transfer that buffered data into
+ * the user buffer.
+ *
+ * First, get the length of the data to transfer.
+ */
+
+ if (readahead->rh_nbytes > pstate->rf_buflen)
+ {
+ recvlen = pstate->rf_buflen;
+ }
+ else
+ {
+ recvlen = readahead->rh_nbytes;
+ }
+
+ if (recvlen > 0)
+ {
+ /* Copy the read-ahead data into the user buffer */
+
+ memcpy(pstate->rf_buffer, readahead->rh_buffer, recvlen);
+ vdbg("Received %d bytes (of %d)\n", recvlen, readahead->rh_nbytes);
+
+ /* Update the accumulated size of the data read */
+
+ pstate->rf_recvlen += recvlen;
+ pstate->rf_buffer += recvlen;
+ pstate->rf_buflen -= recvlen;
+ }
+
+ /* If the read-ahead buffer is empty, then release it. If not, then
+ * we will have to move the data down and return the buffer to the
+ * front of the list.
+ */
+
+ if (recvlen < readahead->rh_nbytes)
+ {
+ readahead->rh_nbytes -= recvlen;
+ memcpy(readahead->rh_buffer, &readahead->rh_buffer[recvlen],
+ readahead->rh_nbytes);
+ sq_addfirst(&readahead->rh_node, &conn->readahead);
+ }
+ else
+ {
+ uip_tcpreadaheadrelease(readahead);
+ }
+ }
+ }
+ while (readahead && pstate->rf_buflen > 0);
+}
+#endif
+
+/****************************************************************************
* Function: recvfrom_timeout
*
* Description:
@@ -449,8 +536,8 @@ static void recvfrom_init(FAR struct socket *psock, FAR void *buf, size_t len,
memset(pstate, 0, sizeof(struct recvfrom_s));
(void)sem_init(&pstate->rf_sem, 0, 0); /* Doesn't really fail */
- pstate->rf_buflen = len;
- pstate->rf_buffer = buf;
+ pstate->rf_buflen = len;
+ pstate->rf_buffer = buf;
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
/* Set up the start time for the timeout */
@@ -538,9 +625,9 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
#endif
{
struct uip_udp_conn *udp_conn;
- struct recvfrom_s state;
- irqstate_t save;
- int ret;
+ struct recvfrom_s state;
+ irqstate_t save;
+ int ret;
/* Perform the UDP recvfrom() operation */
@@ -619,10 +706,10 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR const struct sockaddr_in *infrom )
#endif
{
- struct uip_conn *conn;
- struct recvfrom_s state;
- irqstate_t save;
- int ret;
+ struct uip_conn *conn;
+ struct recvfrom_s state;
+ irqstate_t save;
+ int ret;
/* Verify that the SOCK_STREAM has been connected */
@@ -642,24 +729,38 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
save = irqsave();
recvfrom_init(psock, buf, len, &state);
- /* Set up the callback in the connection */
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
- conn = (struct uip_conn *)psock->s_conn;
- conn->data_private = (void*)&state;
- conn->data_event = recvfrom_tcpinterrupt;
+ /* Handle any any TCP data already buffered in a read-ahead buffer. */
- /* Wait for either the receive to complete or for an error/timeout to occur.
- * NOTES: (1) sem_wait will also terminate if a signal is received, (2)
- * interrupts are disabled! They will be re-enabled while the task sleeps
- * and automatically re-enabled when the task restarts.
+ recvfrom_readahead(&state);
+
+ /* If there is space to receive anything more, then we will
+ * wait to receive the data.
*/
- ret = sem_wait(&state.rf_sem);
+ if (state.rf_buflen > 0)
+#endif
+ {
+ /* Set up the callback in the connection */
- /* Make sure that no further interrupts are processed */
+ conn = (struct uip_conn *)psock->s_conn;
+ conn->data_private = (void*)&state;
+ conn->data_event = recvfrom_tcpinterrupt;
+
+ /* Wait for either the receive to complete or for an error/timeout to occur.
+ * NOTES: (1) sem_wait will also terminate if a signal is received, (2)
+ * interrupts are disabled! They will be re-enabled while the task sleeps
+ * and automatically re-enabled when the task restarts.
+ */
- conn->data_private = NULL;
- conn->data_event = NULL;
+ ret = sem_wait(&state.rf_sem);
+
+ /* Make sure that no further interrupts are processed */
+
+ conn->data_private = NULL;
+ conn->data_event = NULL;
+ }
irqrestore(save);
#warning "Needs to return server address"
diff --git a/nuttx/net/socket.c b/nuttx/net/socket.c
index 5efc86df9..d7c21d01b 100644
--- a/nuttx/net/socket.c
+++ b/nuttx/net/socket.c
@@ -135,7 +135,10 @@ int socket(int domain, int type, int protocol)
psock->s_type = type;
psock->s_conn = NULL;
- /* Allocate the appropriate connection structure */
+ /* Allocate the appropriate connection structure. This reserves the
+ * the connection structure is is unallocated at this point. It will
+ * not actually be initialized until the socket is connected.
+ */
switch (type)
{
diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs
index 8a232ffbf..4256e72e9 100644
--- a/nuttx/net/uip/Make.defs
+++ b/nuttx/net/uip/Make.defs
@@ -50,7 +50,8 @@ endif
# TCP source files
UIP_CSRCS += uip-tcpconn.c uip-tcppoll.c uip-tcptimer.c uip-tcpsend.c \
- uip-tcpinput.c uip-tcpappsend.c uip-listen.c uip-tcpcallback.c
+ uip-tcpinput.c uip-tcpappsend.c uip-listen.c uip-tcpcallback.c \
+ uip-tcpreadahead.c
# UDP source files
diff --git a/nuttx/net/uip/uip-arp.c b/nuttx/net/uip/uip-arp.c
index 13dd1ba03..4d95d16d3 100644
--- a/nuttx/net/uip/uip-arp.c
+++ b/nuttx/net/uip/uip-arp.c
@@ -129,7 +129,7 @@ static const struct uip_eth_addr broadcast_ethaddr =
{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
static const uint16 broadcast_ipaddr[2] = {0xffff, 0xffff};
-static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
+static struct arp_entry arp_table[CONFIG_NET_ARPTAB_SIZE];
static uint8 g_arptime;
@@ -170,7 +170,7 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr)
* inserted in the ARP table.
*/
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i)
+ for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
tabptr = &arp_table[i];
@@ -198,7 +198,7 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr)
/* First, we try to find an unused entry in the ARP table. */
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i)
+ for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
tabptr = &arp_table[i];
if (tabptr->at_ipaddr == 0)
@@ -211,11 +211,11 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr)
* throw it away.
*/
- if (i == UIP_ARPTAB_SIZE)
+ if (i == CONFIG_NET_ARPTAB_SIZE)
{
uint8 tmpage = 0;
int j = 0;
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i)
+ for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
tabptr = &arp_table[i];
if (g_arptime - tabptr->at_time > tmpage)
@@ -246,7 +246,7 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr)
void uip_arp_init(void)
{
int i;
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i)
+ for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
memset(&arp_table[i].at_ipaddr, 0, sizeof(in_addr_t));
}
@@ -265,7 +265,7 @@ void uip_arp_timer(void)
int i;
++g_arptime;
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i)
+ for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
tabptr = &arp_table[i];
if (tabptr->at_ipaddr != 0 && g_arptime - tabptr->at_time >= UIP_ARP_MAXAGE)
@@ -451,7 +451,7 @@ void uip_arp_out(struct uip_driver_s *dev)
/* Check if we already have this destination address in the ARP table */
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i)
+ for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
tabptr = &arp_table[i];
if (uip_ipaddr_cmp(ipaddr, tabptr->at_ipaddr))
@@ -460,7 +460,7 @@ void uip_arp_out(struct uip_driver_s *dev)
}
}
- if (i == UIP_ARPTAB_SIZE)
+ if (i == CONFIG_NET_ARPTAB_SIZE)
{
/* The destination address was not in our ARP table, so we
* overwrite the IP packet with an ARP request.
diff --git a/nuttx/net/uip/uip-chksum.c b/nuttx/net/uip/uip-chksum.c
index c8c173b95..6faaf9817 100644
--- a/nuttx/net/uip/uip-chksum.c
+++ b/nuttx/net/uip/uip-chksum.c
@@ -223,7 +223,7 @@ uint16 uip_udpchksum(struct uip_driver_s *dev)
{
return upper_layer_chksum(dev, UIP_PROTO_UDP);
}
-#endif /* UIP_UDP_CHECKSUMS */
+#endif
#endif /* UIP_ARCH_CHKSUM */
#endif /* CONFIG_NET */
diff --git a/nuttx/net/uip/uip-fw.c b/nuttx/net/uip/uip-fw.c
index 187fb6c39..fa9b5fc4e 100644
--- a/nuttx/net/uip/uip-fw.c
+++ b/nuttx/net/uip/uip-fw.c
@@ -103,15 +103,19 @@ struct icmpip_hdr
};
/* ICMP ECHO. */
+
#define ICMP_ECHO 8
/* ICMP TIME-EXCEEDED. */
+
#define ICMP_TE 11
/* Pointer to the TCP/IP headers of the packet in the d_buf buffer. */
+
#define BUF ((struct tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
/* Pointer to the ICMP/IP headers of the packet in the d_buf buffer. */
+
#define ICMPBUF ((struct icmpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
/* Certain fields of an IP packet that are used for identifying
@@ -158,11 +162,12 @@ void uip_fw_init(void)
{
struct uip_fw_netif *t;
defaultnetif = NULL;
- while(netifs != NULL) {
- t = netifs;
- netifs = netifs->next;
- t->next = NULL;
- }
+ while(netifs != NULL)
+ {
+ t = netifs;
+ netifs = netifs->next;
+ t->next = NULL;
+ }
}
/* Send out an ICMP TIME-EXCEEDED message.
@@ -176,18 +181,24 @@ static void time_exceeded(struct uip_driver_s *dev)
in_addr_t tmp_addr;
/* We don't send out ICMP errors for ICMP messages. */
- if (ICMPBUF->proto == UIP_PROTO_ICMP) {
- dev->d_len = 0;
- return;
- }
+
+ if (ICMPBUF->proto == UIP_PROTO_ICMP)
+ {
+ dev->d_len = 0;
+ return;
+ }
+
/* Copy fields from packet header into payload of this ICMP packet. */
+
memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28);
/* Set the ICMP type and code. */
- ICMPBUF->type = ICMP_TE;
+
+ ICMPBUF->type = ICMP_TE;
ICMPBUF->icode = 0;
/* Calculate the ICMP checksum. */
+
ICMPBUF->icmpchksum = 0;
ICMPBUF->icmpchksum = ~uip_chksum((uint16 *)&(ICMPBUF->type), 36);
@@ -195,30 +206,34 @@ static void time_exceeded(struct uip_driver_s *dev)
* original packet.
*/
- tmp_addr = BUF->destipaddr;
+ tmp_addr = BUF->destipaddr;
BUF->destipaddr = BUF->srcipaddr;
- BUF->srcipaddr = tmp_addr;
+ BUF->srcipaddr = tmp_addr;
/* Set our IP address as the source address. */
BUF->srcipaddr = dev->d_ipaddr;
/* The size of the ICMP time exceeded packet is 36 + the size of the
- IP header (20) = 56. */
- dev->d_len = 56;
+ * IP header (20) = 56.
+ */
+
+ dev->d_len = 56;
ICMPBUF->len[0] = 0;
ICMPBUF->len[1] = dev->d_len;
/* Fill in the other fields in the IP header. */
- ICMPBUF->vhl = 0x45;
- ICMPBUF->tos = 0;
+
+ ICMPBUF->vhl = 0x45;
+ ICMPBUF->tos = 0;
ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0;
- ICMPBUF->ttl = UIP_TTL;
- ICMPBUF->proto = UIP_PROTO_ICMP;
+ ICMPBUF->ttl = UIP_TTL;
+ ICMPBUF->proto = UIP_PROTO_ICMP;
/* Calculate IP checksum. */
- ICMPBUF->ipchksum = 0;
- ICMPBUF->ipchksum = ~(uip_ipchksum(dev));
+
+ ICMPBUF->ipchksum = 0;
+ ICMPBUF->ipchksum = ~(uip_ipchksum(dev));
}
/* Register a packet in the forwarding cache so that it won't be
@@ -231,31 +246,36 @@ static void fwcache_register(struct uip_driver_s *dev)
int i, oldest;
oldest = FW_TIME;
- fw = NULL;
+ fw = NULL;
/* Find the oldest entry in the cache. */
- for (i = 0; i < FWCACHE_SIZE; ++i) {
- if (fwcache[i].timer == 0) {
- fw = &fwcache[i];
- break;
- } else if (fwcache[i].timer <= oldest) {
- fw = &fwcache[i];
- oldest = fwcache[i].timer;
+
+ for (i = 0; i < FWCACHE_SIZE; ++i)
+ {
+ if (fwcache[i].timer == 0)
+ {
+ fw = &fwcache[i];
+ break;
+ }
+ else if (fwcache[i].timer <= oldest)
+ {
+ fw = &fwcache[i];
+ oldest = fwcache[i].timer;
+ }
}
- }
- fw->timer = FW_TIME;
- fw->ipid = BUF->ipid;
- fw->srcipaddr = BUF->srcipaddr;
+ fw->timer = FW_TIME;
+ fw->ipid = BUF->ipid;
+ fw->srcipaddr = BUF->srcipaddr;
fw->destipaddr = BUF->destipaddr;
- fw->proto = BUF->proto;
+ fw->proto = BUF->proto;
#if notdef
fw->payload[0] = BUF->srcport;
fw->payload[1] = BUF->destport;
#endif
#if UIP_REASSEMBLY > 0
- fw->len = BUF->len;
- fw->offset = BUF->ipoffset;
+ fw->len = BUF->len;
+ fw->offset = BUF->ipoffset;
#endif
}
@@ -301,35 +321,44 @@ uint8 uip_fw_output(struct uip_driver_s *dev)
{
struct uip_fw_netif *netif;
- if (dev->d_len == 0) {
- return UIP_FW_ZEROLEN;
- }
+ if (dev->d_len == 0)
+ {
+ return UIP_FW_ZEROLEN;
+ }
fwcache_register(dev);
-#if UIP_BROADCAST
+#ifdef CONFIG_NET_BROADCAST
/* Link local broadcasts go out on all interfaces. */
+
if (/*BUF->proto == UIP_PROTO_UDP &&*/
- BUF->destipaddr[0] == 0xffff &&
- BUF->destipaddr[1] == 0xffff) {
- if (defaultnetif != NULL) {
- defaultnetif->output();
- }
- for (netif = netifs; netif != NULL; netif = netif->next) {
- netif->output();
+ BUF->destipaddr[0] == 0xffff &&
+ BUF->destipaddr[1] == 0xffff)
+ {
+ if (defaultnetif != NULL)
+ {
+ defaultnetif->output();
+ }
+ for (netif = netifs; netif != NULL; netif = netif->next)
+ {
+ netif->output();
+ }
+ return UIP_FW_OK;
}
- return UIP_FW_OK;
- }
-#endif /* UIP_BROADCAST */
+#endif
netif = find_netif (dev);
dbg("netif: %p output: %p len: %d\n", netif, netif->output, dev->d_len);
- if (netif == NULL) {
- return UIP_FW_NOROUTE;
- }
+ if (netif == NULL)
+ {
+ return UIP_FW_NOROUTE;
+ }
+
/* If we now have found a suitable network interface, we call its
- output function to send out the packet. */
+ * output function to send out the packet.
+ */
+
return netif->output();
}
@@ -353,39 +382,43 @@ uint8 uip_fw_forward(struct uip_driver_s *dev)
}
/* If we use ping IP address configuration, and our IP address is
- not yet configured, we should intercept all ICMP echo packets. */
-#if UIP_PINGADDRCONF
+ * not yet configured, we should intercept all ICMP echo packets.
+ */
+
+#ifdef CONFIG_NET_PINGADDRCONF
if (dev->d_ipaddr == 0 && BUF->proto == UIP_PROTO_ICMP && ICMPBUF->type == ICMP_ECHO)
{
return UIP_FW_LOCAL;
}
-#endif /* UIP_PINGADDRCONF */
+#endif
/* Check if the packet is in the forwarding cache already, and if so
we drop it. */
- for (fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
- if (fw->timer != 0 &&
+ for (fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw)
+ {
+ if (fw->timer != 0 &&
#if UIP_REASSEMBLY > 0
- fw->len == BUF->len &&
- fw->offset == BUF->ipoffset &&
+ fw->len == BUF->len &&
+ fw->offset == BUF->ipoffset &&
#endif
- fw->ipid == BUF->ipid &&
- fw->srcipaddr == BUF->srcipaddr &&
- fw->destipaddr == BUF->destipaddr &&
+ fw->ipid == BUF->ipid &&
+ fw->srcipaddr == BUF->srcipaddr &&
+ fw->destipaddr == BUF->destipaddr &&
#if notdef
- fw->payload[0] == BUF->srcport &&
- fw->payload[1] == BUF->destport &&
+ fw->payload[0] == BUF->srcport &&
+ fw->payload[1] == BUF->destport &&
#endif
- fw->proto == BUF->proto) {
- /* Drop packet. */
- return UIP_FW_FORWARDED;
+ fw->proto == BUF->proto)
+ {
+ /* Drop packet. */
+ return UIP_FW_FORWARDED;
+ }
}
- }
/* If the TTL reaches zero we produce an ICMP time exceeded message
- in the d_buf buffer and forward that packet back to the sender
- of the packet.
+ * in the d_buf buffer and forward that packet back to the sender
+ * of the packet.
*/
if (BUF->ttl <= 1)
@@ -400,28 +433,37 @@ uint8 uip_fw_forward(struct uip_driver_s *dev)
}
/* Decrement the TTL (time-to-live) value in the IP header */
+
BUF->ttl = BUF->ttl - 1;
/* Update the IP checksum. */
- if (BUF->ipchksum >= HTONS(0xffff - 0x0100)) {
- BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1;
- } else {
- BUF->ipchksum = BUF->ipchksum + HTONS(0x0100);
- }
-
- if (dev->d_len > 0) {
- dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN];
- uip_fw_output(dev);
- }
-
-#if UIP_BROADCAST
- if (BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) {
- return UIP_FW_LOCAL;
- }
-#endif /* UIP_BROADCAST */
+
+ if (BUF->ipchksum >= HTONS(0xffff - 0x0100))
+ {
+ BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1;
+ }
+ else
+ {
+ BUF->ipchksum = BUF->ipchksum + HTONS(0x0100);
+ }
+
+ if (dev->d_len > 0)
+ {
+ dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN];
+ uip_fw_output(dev);
+ }
+
+#ifdef CONFIG_NET_BROADCAST
+ if (BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff)
+ {
+ return UIP_FW_LOCAL;
+ }
+#endif
/* Return non-zero to indicate that the packet was forwarded and that no
- other processing should be made. */
+ * other processing should be made.
+ */
+
return UIP_FW_FORWARDED;
}
@@ -434,7 +476,7 @@ uint8 uip_fw_forward(struct uip_driver_s *dev)
void uip_fw_register(struct uip_fw_netif *netif)
{
netif->next = netifs;
- netifs = netif;
+ netifs = netif;
}
/* Register a default network interface.
@@ -456,9 +498,11 @@ void uip_fw_default(struct uip_fw_netif *netif)
void uip_fw_periodic(void)
{
struct fwcache_entry *fw;
- for (fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
- if (fw->timer > 0) {
- --fw->timer;
+ for (fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw)
+ {
+ if (fw->timer > 0)
+ {
+ --fw->timer;
+ }
}
- }
}
diff --git a/nuttx/net/uip/uip-icmpinput.c b/nuttx/net/uip/uip-icmpinput.c
index 8dd276330..5dae94bd7 100644
--- a/nuttx/net/uip/uip-icmpinput.c
+++ b/nuttx/net/uip/uip-icmpinput.c
@@ -119,12 +119,12 @@ void uip_icmpinput(struct uip_driver_s *dev)
* ourself.
*/
-#if UIP_PINGADDRCONF
+#ifdef CONFIG_NET_PINGADDRCONF
if (dev->d_ipaddr == 0)
{
dev->d_ipaddr = ICMPBUF->destipaddr;
}
-#endif /* UIP_PINGADDRCONF */
+#endif
ICMPBUF->type = ICMP_ECHO_REPLY;
diff --git a/nuttx/net/uip/uip-initialize.c b/nuttx/net/uip/uip-initialize.c
index 3a7701cbe..2e00c5d9c 100644
--- a/nuttx/net/uip/uip-initialize.c
+++ b/nuttx/net/uip/uip-initialize.c
@@ -125,6 +125,12 @@ void uip_initialize(void)
uip_tcpinit();
+ /* Initialize the TCP/IP read-ahead buffering */
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ uip_tcpreadaheadinit();
+#endif
+
/* Initialize the UDP connection structures */
#ifdef CONFIG_NET_UDP
diff --git a/nuttx/net/uip/uip-input.c b/nuttx/net/uip/uip-input.c
index 1c3de79e6..71f9b8b9a 100644
--- a/nuttx/net/uip/uip-input.c
+++ b/nuttx/net/uip/uip-input.c
@@ -108,7 +108,7 @@
/* IP fragment re-assembly */
#define IP_MF 0x20
-#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
+#define UIP_REASS_BUFSIZE (CONFIG_NET_BUFSIZE - UIP_LLH_LEN)
#define UIP_REASS_FLAG_LASTFRAG 0x01
/****************************************************************************
@@ -392,7 +392,7 @@ void uip_input(struct uip_driver_s *dev)
* packets.
*/
-#if UIP_PINGADDRCONF && !CONFIG_NET_IPv6
+#if defined(CONFIG_NET_PINGADDRCONF) && !defined(CONFIG_NET_IPv6)
if (BUF->proto == UIP_PROTO_ICMP)
{
dbg("Possible ping config packet received\n");
@@ -400,7 +400,7 @@ void uip_input(struct uip_driver_s *dev)
goto done;
}
else
-#endif /* UIP_PINGADDRCONF */
+#endif
{
dbg("No IP address assigned\n");
goto drop;
@@ -412,13 +412,13 @@ void uip_input(struct uip_driver_s *dev)
* UDP packet, which may be destined to us.
*/
-#if UIP_BROADCAST
+#ifdef CONFIG_NET_BROADCAST
if (BUF->proto == UIP_PROTO_UDP && uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
{
uip_udpinput(dev);
return;
}
-#endif /* UIP_BROADCAST */
+#endif
/* Check if the packet is destined for our IP address. */
#ifndef CONFIG_NET_IPv6
diff --git a/nuttx/net/uip/uip-internal.h b/nuttx/net/uip/uip-internal.h
index 118ccd53f..c358d431f 100644
--- a/nuttx/net/uip/uip-internal.h
+++ b/nuttx/net/uip/uip-internal.h
@@ -194,6 +194,14 @@ EXTERN void uip_udpcallback(struct uip_driver_s *dev,
EXTERN void uip_icmpinput(struct uip_driver_s *dev);
+/* Defined in uip-tcpreadahead.c ********************************************/
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+EXTERN void uip_tcpreadaheadinit(void);
+EXTERN struct uip_readahead_s *uip_tcpreadaheadalloc(void);
+EXTERN void uip_tcpreadaheadrelease(struct uip_readahead_s *buf);
+#endif /* CONFIG_NET_NTCP_READAHEAD_BUFFERS */
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/nuttx/net/uip/uip-listen.c b/nuttx/net/uip/uip-listen.c
index e7ee8ffc3..643d054cb 100644
--- a/nuttx/net/uip/uip-listen.c
+++ b/nuttx/net/uip/uip-listen.c
@@ -57,7 +57,7 @@
/* The uip_listenports list all currently listening ports. */
-static uint16 uip_listenports[UIP_LISTENPORTS];
+static uint16 uip_listenports[CONFIG_NET_MAX_LISTENPORTS];
/****************************************************************************
* Private Functions
@@ -82,7 +82,7 @@ static uint16 uip_listenports[UIP_LISTENPORTS];
void uip_listeninit(void)
{
int ndx;
- for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++)
+ for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++)
{
uip_listenports[ndx] = 0;
}
@@ -106,7 +106,7 @@ int uip_unlisten(uint16 port)
int ret = -EINVAL;
flags = irqsave();
- for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++)
+ for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++)
{
if (uip_listenports[ndx] == port)
{
@@ -137,7 +137,7 @@ int uip_listen(uint16 port)
int ret = -ENOBUFS;
flags = irqsave();
- for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++)
+ for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++)
{
if (uip_listenports[ndx] == 0)
{
@@ -164,7 +164,7 @@ int uip_listen(uint16 port)
boolean uip_islistener(uint16 portno)
{
int ndx;
- for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++)
+ for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++)
{
if (uip_listenports[ndx] == portno)
{
diff --git a/nuttx/net/uip/uip-send.c b/nuttx/net/uip/uip-send.c
index 6cdfd7252..93096168a 100644
--- a/nuttx/net/uip/uip-send.c
+++ b/nuttx/net/uip/uip-send.c
@@ -93,7 +93,7 @@
void uip_send(struct uip_driver_s *dev, const void *buf, int len)
{
- if (dev && len > 0 && len < UIP_BUFSIZE)
+ if (dev && len > 0 && len < CONFIG_NET_BUFSIZE)
{
dev->d_sndlen = len;
memcpy(dev->d_snddata, buf, len );
diff --git a/nuttx/net/uip/uip-setipid.c b/nuttx/net/uip/uip-setipid.c
index 71467b0f8..5726c7c7a 100644
--- a/nuttx/net/uip/uip-setipid.c
+++ b/nuttx/net/uip/uip-setipid.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * net/uip/uip-udpcallback.c
+ * net/uip/uip-setipid.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
diff --git a/nuttx/net/uip/uip-split.c b/nuttx/net/uip/uip-split.c
index 8d75487d2..68b19d275 100644
--- a/nuttx/net/uip/uip-split.c
+++ b/nuttx/net/uip/uip-split.c
@@ -42,85 +42,103 @@
void uip_split_output(struct uip_driver_s *dev)
{
- uint16 tcplen, len1, len2;
+ uint16 tcplen;
+ uint16 len1;
+ uint16 len2;
/* We only try to split maximum sized TCP segments. */
- if(BUF->proto == UIP_PROTO_TCP &&
- dev->d_len == UIP_BUFSIZE - UIP_LLH_LEN) {
-
- tcplen = dev->d_len - UIP_TCPIP_HLEN;
- /* Split the segment in two. If the original packet length was
- odd, we make the second packet one byte larger. */
- len1 = len2 = tcplen / 2;
- if(len1 + len2 < tcplen) {
- ++len2;
- }
- /* Create the first packet. This is done by altering the length
- field of the IP header and updating the checksums. */
- dev->d_len = len1 + UIP_TCPIP_HLEN;
+ if (BUF->proto == UIP_PROTO_TCP &&
+ dev->d_len == CONFIG_NET_BUFSIZE - UIP_LLH_LEN)
+ {
+ tcplen = dev->d_len - UIP_TCPIP_HLEN;
+
+ /* Split the segment in two. If the original packet length was
+ * odd, we make the second packet one byte larger.
+ */
+
+ len1 = len2 = tcplen / 2;
+ if (len1 + len2 < tcplen)
+ {
+ ++len2;
+ }
+
+ /* Create the first packet. This is done by altering the length
+ * field of the IP header and updating the checksums.
+ */
+
+ dev->d_len = len1 + UIP_TCPIP_HLEN;
#ifdef CONFIG_NET_IPv6
- /* For IPv6, the IP length field does not include the IPv6 IP header
- length. */
- BUF->len[0] = ((dev->d_len - UIP_IPH_LEN) >> 8);
- BUF->len[1] = ((dev->d_len - UIP_IPH_LEN) & 0xff);
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ * length.
+ */
+ BUF->len[0] = ((dev->d_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((dev->d_len - UIP_IPH_LEN) & 0xff);
#else /* CONFIG_NET_IPv6 */
- BUF->len[0] = dev->d_len >> 8;
- BUF->len[1] = dev->d_len & 0xff;
+ BUF->len[0] = dev->d_len >> 8;
+ BUF->len[1] = dev->d_len & 0xff;
#endif /* CONFIG_NET_IPv6 */
- /* Recalculate the TCP checksum. */
- BUF->tcpchksum = 0;
- BUF->tcpchksum = ~(uip_tcpchksum(dev));
+ /* Recalculate the TCP checksum. */
+
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum(dev));
#ifndef CONFIG_NET_IPv6
- /* Recalculate the IP checksum. */
- BUF->ipchksum = 0;
- BUF->ipchksum = ~(uip_ipchksum(dev));
+ /* Recalculate the IP checksum. */
+
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum(dev));
#endif /* CONFIG_NET_IPv6 */
- /* Transmit the first packet. */
- /* uip_fw_output();*/
- tcpip_output();
+ /* Transmit the first packet. */
+ /* uip_fw_output();*/
+ tcpip_output();
+
+ /* Now, create the second packet. To do this, it is not enough to
+ * just alter the length field, but we must also update the TCP
+ * sequence number and point the d_appdata to a new place in
+ * memory. This place is detemined by the length of the first
+ * packet (len1).
+ */
- /* Now, create the second packet. To do this, it is not enough to
- just alter the length field, but we must also update the TCP
- sequence number and point the d_appdata to a new place in
- memory. This place is detemined by the length of the first
- packet (len1). */
- dev->d_len = len2 + UIP_TCPIP_HLEN;
+ dev->d_len = len2 + UIP_TCPIP_HLEN;
#ifdef CONFIG_NET_IPv6
- /* For IPv6, the IP length field does not include the IPv6 IP header
- length. */
- BUF->len[0] = ((dev->d_len - UIP_IPH_LEN) >> 8);
- BUF->len[1] = ((dev->d_len - UIP_IPH_LEN) & 0xff);
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ * length.
+ */
+
+ BUF->len[0] = ((dev->d_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((dev->d_len - UIP_IPH_LEN) & 0xff);
#else /* CONFIG_NET_IPv6 */
- BUF->len[0] = dev->d_len >> 8;
- BUF->len[1] = dev->d_len & 0xff;
+ BUF->len[0] = dev->d_len >> 8;
+ BUF->len[1] = dev->d_len & 0xff;
#endif /* CONFIG_NET_IPv6 */
- /* dev->d_appdata += len1;*/
- memcpy(dev->d_appdata, dev->d_appdata + len1, len2);
+ /* dev->d_appdata += len1;*/
+ memcpy(dev->d_appdata, dev->d_appdata + len1, len2);
- uip_incr32(BUF->seqno, len1);
+ uip_incr32(BUF->seqno, len1);
- /* Recalculate the TCP checksum. */
+ /* Recalculate the TCP checksum. */
- BUF->tcpchksum = 0;
- BUF->tcpchksum = ~(uip_tcpchksum(dev));
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum(dev));
#ifndef CONFIG_NET_IPv6
- /* Recalculate the IP checksum. */
+ /* Recalculate the IP checksum. */
- BUF->ipchksum = 0;
- BUF->ipchksum = ~(uip_ipchksum(dev));
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum(dev));
#endif /* CONFIG_NET_IPv6 */
- /* Transmit the second packet. */
- /* uip_fw_output();*/
- tcpip_output();
- } else {
- /* uip_fw_output();*/
- tcpip_output();
- }
+ /* Transmit the second packet. */
+ /* uip_fw_output();*/
+ tcpip_output();
+ }
+ else
+ {
+ /* uip_fw_output();*/
+ tcpip_output();
+ }
}
diff --git a/nuttx/net/uip/uip-tcpcallback.c b/nuttx/net/uip/uip-tcpcallback.c
index 973a2f2a2..311323059 100644
--- a/nuttx/net/uip/uip-tcpcallback.c
+++ b/nuttx/net/uip/uip-tcpcallback.c
@@ -42,6 +42,7 @@
#ifdef CONFIG_NET
#include <sys/types.h>
+#include <string.h>
#include <debug.h>
#include <net/uip/uipopt.h>
@@ -59,6 +60,89 @@
****************************************************************************/
/****************************************************************************
+ * Function: uip_dataevent
+ *
+ * Description:
+ * This is the default data_event handler that is called when there is no
+ * use data handler in place
+ *
+ * Assumptions:
+ * This function is called at the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static inline uint8
+uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
+{
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ struct uip_readahead_s *readahead;
+ uint16 recvlen;
+#endif
+ uint8 ret = flags;
+
+ /* Is there new data? With non-zero length? (Certain connection events
+ * can have zero-length with UIP_NEWDATA set just to cause an ACK).
+ */
+
+ if (uip_newdata_event(flags) && dev->d_len > 0)
+ {
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ /* Allocate a read-ahead buffer to hold the newly received data */
+
+ readahead = uip_tcpreadaheadalloc();
+ if (readahead)
+ {
+ /* Get the length of the data to buffer. If the sizes of the
+ * read-ahead buffers are picked correct, they should always
+ * hold the full received packet.\
+ */
+
+ if (dev->d_len > CONFIG_NET_TCP_READAHEAD_BUFSIZE)
+ {
+ recvlen = CONFIG_NET_TCP_READAHEAD_BUFSIZE;
+ }
+ else
+ {
+ recvlen = dev->d_len;
+ }
+
+ /* Copy the new appdata into the read-ahead buffer */
+
+ memcpy(readahead->rh_buffer, dev->d_appdata, recvlen);
+ readahead->rh_nbytes = recvlen;
+ vdbg("Buffered %d bytes (of %d)\n", recvlen, dev->d_len);
+
+ /* Save the readahead buffer in the connection structure where
+ * it can be found with recv() is called.
+ */
+
+ sq_addlast(&readahead->rh_node, &conn->readahead);
+
+ /* Indicate that all of the data in the buffer has been consumed */
+
+ dev->d_len = 0;
+ }
+ else
+#endif
+ {
+ /* There is no handler to receive new data and there are no free
+ * read-ahead buffers to retain the data. In this case, clear the
+ * UIP_NEWDATA bit so that no ACK will be sent and drop the packet.
+ */
+
+#ifdef CONFIG_NET_STATISTICS
+ uip_stat.tcp.syndrop++;
+ uip_stat.tcp.drop++;
+#endif
+ ret &= ~UIP_NEWDATA;
+ dev->d_len = 0;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -104,23 +188,12 @@ uint8 uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint8 fla
ret = conn->data_event(dev, conn, flags);
}
- else if ((flags & UIP_CONN_EVENTS) == 0)
+ else
{
- /* There is no handler to receive new data in place and this is not a
- * connection event (which may also include new data that must be ACKed).
- * In this case, clear the UIP_NEWDATA bit so that no ACK will be sent
- * and drop the packet.
- */
-
- dbg("No listener on connection\n");
-
-#ifdef CONFIG_NET_STATISTICS
- uip_stat.tcp.syndrop++;
- uip_stat.tcp.drop++;
-#endif
+ /* There is no handler to receive new data in place */
- ret &= ~UIP_NEWDATA;
- dev->d_len = 0;
+ vdbg("No listener on connection\n");
+ ret = uip_dataevent(dev, conn, flags);
}
/* Check if there is a connection-related event and a connection
diff --git a/nuttx/net/uip/uip-tcpconn.c b/nuttx/net/uip/uip-tcpconn.c
index c0c151570..edeb464ec 100644
--- a/nuttx/net/uip/uip-tcpconn.c
+++ b/nuttx/net/uip/uip-tcpconn.c
@@ -70,7 +70,7 @@
/* The array containing all uIP TCP connections. */
-static struct uip_conn g_tcp_connections[UIP_CONNS];
+static struct uip_conn g_tcp_connections[CONFIG_NET_TCP_CONNS];
/* A list of all free TCP connections */
@@ -186,7 +186,7 @@ void uip_tcpinit(void)
/* Now initialize each connection structure */
- for (i = 0; i < UIP_CONNS; i++)
+ for (i = 0; i < CONFIG_NET_TCP_CONNS; i++)
{
/* Mark the connection closed and move it to the free list */
@@ -394,7 +394,7 @@ struct uip_conn *uip_tcplistener(uint16 portno)
/* Check if this port number is in use by any active UIP TCP connection */
- for (i = 0; i < UIP_CONNS; i++)
+ for (i = 0; i < CONFIG_NET_TCP_CONNS; i++)
{
conn = &g_tcp_connections[i];
if (conn->tcpstateflags != UIP_CLOSED && conn->lport == portno)
@@ -450,12 +450,18 @@ struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf)
conn->rcv_nxt[1] = buf->seqno[1];
conn->rcv_nxt[0] = buf->seqno[0];
+ /* Initialize the list of TCP read-ahead buffers */
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ sq_init(&conn->readahead);
+#endif
+
/* And, finally, put the connection structure into the active list.
* Interrupts should already be disabled in this context.
*/
dq_addlast(&conn->node, &g_active_tcp_connections);
- }
+ }
return conn;
}
@@ -615,6 +621,12 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr)
uip_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr);
+ /* Initialize the list of TCP read-ahead buffers */
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ sq_init(&conn->readahead);
+#endif
+
/* And, finally, put the connection structure into the active
* list. Because g_active_tcp_connections is accessed from user level and
* interrupt level, code, it is necessary to keep interrupts disabled during
diff --git a/nuttx/net/uip/uip-tcpinput.c b/nuttx/net/uip/uip-tcpinput.c
index 5ce3e2df6..1a74d5f81 100644
--- a/nuttx/net/uip/uip-tcpinput.c
+++ b/nuttx/net/uip/uip-tcpinput.c
@@ -265,7 +265,7 @@ void uip_tcpinput(struct uip_driver_s *dev)
found:
- flags = 0;
+ flags = 0;
/* We do a very naive form of TCP reset processing; we just accept
* any RST and kill our connection. We should in fact check if the
diff --git a/nuttx/net/uip/uip-tcpreadahead.c b/nuttx/net/uip/uip-tcpreadahead.c
new file mode 100644
index 000000000..6c4c78f1e
--- /dev/null
+++ b/nuttx/net/uip/uip-tcpreadahead.c
@@ -0,0 +1,132 @@
+/****************************************************************************
+ * net/uip/uip-tcpreadahead.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <net/uip/uipopt.h>
+#if defined(CONFIG_NET) && (CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0)
+
+#include <sys/types.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <net/uip/uip.h>
+
+#include "uip-internal.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* These are the pre-allocated read-ahead buffers */
+
+static struct uip_readahead_s g_buffers[CONFIG_NET_NTCP_READAHEAD_BUFFERS];
+
+/* This is the list of available read-ahead buffers */
+
+static sq_queue_t g_freebuffers;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: uip_tcpreadaheadinit
+ *
+ * Description:
+ * Initialize the list of free read-ahead buffers
+ *
+ * Assumptions:
+ * Called once early initialization.
+ *
+ ****************************************************************************/
+
+void uip_tcpreadaheadinit(void)
+{
+ int i;
+
+ sq_init(&g_freebuffers);
+ for (i = 0; i < CONFIG_NET_NTCP_READAHEAD_BUFFERS; i++)
+ {
+ sq_addfirst(&g_buffers[i].rh_node, &g_freebuffers);
+ }
+}
+
+/****************************************************************************
+ * Function: uip_tcpreadaheadalloc
+ *
+ * Description:
+ * Allocate a TCP read-ahead buffer by taking a pre-allocated buffer from
+ * the free list. This function is called from TCP logic when new,
+ * incoming TCP data is received but there is no user logic recving the
+ * the data. Note: malloc() cannot be used because this function is
+ * called from interrupt level.
+ *
+ * Assumptions:
+ * Called from interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+struct uip_readahead_s *uip_tcpreadaheadalloc(void)
+{
+ return (struct uip_readahead_s*)sq_remfirst(&g_freebuffers);
+}
+
+/****************************************************************************
+ * Function: uip_tcpreadaheadrelease
+ *
+ * Description:
+ * Release a TCP read-ahead buffer by returning the buffer to the free list.
+ * This function is called from user logic after it is consumed the buffered
+ * data.
+ *
+ * Assumptions:
+ * Called from user logic BUT with interrupts disabled.
+ *
+ ****************************************************************************/
+
+void uip_tcpreadaheadrelease(struct uip_readahead_s *buf)
+{
+ sq_addfirst(&buf->rh_node, &g_freebuffers);
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_NTCP_READAHEAD_BUFFERS*/
diff --git a/nuttx/net/uip/uip-tcpsend.c b/nuttx/net/uip/uip-tcpsend.c
index 31766d202..02123bc82 100644
--- a/nuttx/net/uip/uip-tcpsend.c
+++ b/nuttx/net/uip/uip-tcpsend.c
@@ -199,8 +199,8 @@ static void uip_tcpsendcommon(struct uip_driver_s *dev, struct uip_conn *conn)
}
else
{
- BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
- BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
+ BUF->wnd[0] = ((CONFIG_NET_TCP_CONNS) >> 8);
+ BUF->wnd[1] = ((CONFIG_NET_TCP_CONNS) & 0xff);
}
/* Finish the IP portion of the message, calculate checksums and send
diff --git a/nuttx/net/uip/uip-udpconn.c b/nuttx/net/uip/uip-udpconn.c
index 87ca3f8a6..b904aaac5 100644
--- a/nuttx/net/uip/uip-udpconn.c
+++ b/nuttx/net/uip/uip-udpconn.c
@@ -66,7 +66,7 @@
/* The array containing all uIP UDP connections. */
-struct uip_udp_conn g_udp_connections[UIP_UDP_CONNS];
+struct uip_udp_conn g_udp_connections[CONFIG_NET_UDP_CONNS];
/* A list of all free UDP connections */
@@ -124,7 +124,7 @@ static struct uip_udp_conn *uip_find_conn( uint16 portno )
/* Now search each connection structure.*/
- for (i = 0; i < UIP_UDP_CONNS; i++)
+ for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
{
if (g_udp_connections[ i ].lport == portno)
{
@@ -158,7 +158,7 @@ void uip_udpinit(void)
dq_init(&g_active_udp_connections);
sem_init(&g_free_sem, 0, 1);
- for (i = 0; i < UIP_UDP_CONNS; i++)
+ for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
{
/* Mark the connection closed and move it to the free list */
diff --git a/nuttx/net/uip/uip-udpsend.c b/nuttx/net/uip/uip-udpsend.c
index 7a2a0547c..8f77f78a2 100644
--- a/nuttx/net/uip/uip-udpsend.c
+++ b/nuttx/net/uip/uip-udpsend.c
@@ -160,7 +160,7 @@ void uip_udpsend(struct uip_driver_s *dev, struct uip_udp_conn *conn)
}
#else
UDPBUF->udpchksum = 0;
-#endif /* UIP_UDP_CHECKSUMS */
+#endif
vdbg("Outgoing UDP packet length: %d (%d)\n",
dev->d_len, (UDPBUF->len[0] << 8) | UDPBUF->len[1]);
diff --git a/nuttx/netutils/uiplib/uip-server.c b/nuttx/netutils/uiplib/uip-server.c
index aa0ea5b11..8baccf33d 100644
--- a/nuttx/netutils/uiplib/uip-server.c
+++ b/nuttx/netutils/uiplib/uip-server.c
@@ -41,8 +41,9 @@
#include <sys/socket.h>
#include <netinet/in.h>
+#include <stdio.h>
#include <unistd.h>
-#include <sched.h>
+#include <pthread.h>
#include <errno.h>
#include <debug.h>
@@ -75,15 +76,15 @@
*
****************************************************************************/
-void uip_server(uint16 portno, main_t handler, int stacksize)
+void uip_server(uint16 portno, pthread_startroutine_t handler, int stacksize)
{
struct sockaddr_in myaddr;
#ifdef CONFIG_NET_HAVE_SOLINGER
struct linger ling;
#endif
- struct sched_param param;
+ pthread_t child;
+ pthread_attr_t attr;
socklen_t addrlen;
- const char *argv[2];
int listensd;
int acceptsd;
#ifdef CONFIG_NET_HAVE_REUSEADDR
@@ -142,7 +143,7 @@ void uip_server(uint16 portno, main_t handler, int stacksize)
dbg("accept failure: %d\n", errno);
break;;
}
- dbg("Connection accepted -- spawning\n");
+ dbg("Connection accepted -- spawning sd=%d\n", acceptsd);
/* Configure to "linger" until all data is sent when the socket is closed */
@@ -157,33 +158,25 @@ void uip_server(uint16 portno, main_t handler, int stacksize)
}
#endif
- /* Spawn a thread to handle the connection. The socket descriptor +1 is
- * provided in as the single argument to the new thread. (The +1 is intended
- * to handle the valid, zero file descriptor).
+ /* Create a thread to handle the connection. The socket descriptor is
+ * provided in as the single argument to the new thread.
*/
- if (sched_getparam(0, &param) < 0)
- {
- close(acceptsd);
- dbg("sched_getparam failed: %d\n", errno);
- break;;
- }
-
- argv[0] = (char*)(acceptsd + 1);
- argv[1] = NULL;
+ (void)pthread_attr_init(&attr);
+ (void)pthread_attr_setstacksize(&attr, stacksize);
- if (task_create("", param.sched_priority, stacksize, handler, argv) < 0)
+ if (pthread_create(&child, &attr, handler, (void*)acceptsd) != 0)
{
close(acceptsd);
- dbg("task_create failed: %d\n", errno);
- break;;
+ dbg("create_create failed\n");
+ break;
}
- /* We can close our copy of acceptsd now. This file descriptor was dup'ed
- * by task_create and we no longer need to retain the reference.
+ /* We don't care when/how the child thread exits so detach from it now
+ * in order to avoid memory leaks.
*/
- close(acceptsd);
+ (void)pthread_detach(child);
}
errout_with_socket:
diff --git a/nuttx/netutils/webserver/httpd-cgi.c b/nuttx/netutils/webserver/httpd-cgi.c
index e93aff1be..ab39711c8 100644
--- a/nuttx/netutils/webserver/httpd-cgi.c
+++ b/nuttx/netutils/webserver/httpd-cgi.c
@@ -136,7 +136,7 @@ static void tcp_stats(struct httpd_state *pstate, char *ptr)
struct httpd_state *pstate = (struct httpd_state *)arg;
char buffer[256];
- for(pstate->count = 0; pstate->count < UIP_CONNS; ++pstate->count)
+ for(pstate->count = 0; pstate->count < CONFIG_NET_TCP_CONNS; ++pstate->count)
{
conn = &uip_conns[pstate->count];
if((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
diff --git a/nuttx/netutils/webserver/httpd.c b/nuttx/netutils/webserver/httpd.c
index 2db3436d7..33f93d9b8 100644
--- a/nuttx/netutils/webserver/httpd.c
+++ b/nuttx/netutils/webserver/httpd.c
@@ -51,7 +51,10 @@
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
+#include <pthread.h>
+#include <errno.h>
#include <debug.h>
#include <net/uip/uip.h>
@@ -74,6 +77,8 @@
#define ISO_slash 0x2f
#define ISO_colon 0x3a
+#define errno *get_errno_ptr()
+
#define CONFIG_NETUTILS_HTTPD_DUMPBUFFER 1
/****************************************************************************
@@ -111,7 +116,7 @@ static void httpd_dumpbuffer(struct httpd_state *pstate, ssize_t nbytes)
sprintf(&line[strlen(line)], "%c", ch >= 0x20 && ch <= 0x7e ? ch : '.');
}
}
- dbg("%s", line);
+ dbg("%s\n", line);
}
#endif
}
@@ -131,57 +136,69 @@ static void handle_script(struct httpd_state *pstate)
{
char *ptr;
- while(pstate->file.len > 0) {
-
- /* Check if we should start executing a script */
+ while(pstate->file.len > 0)
+ {
+ /* Check if we should start executing a script */
- if (*pstate->file.data == ISO_percent &&
- *(pstate->file.data + 1) == ISO_bang) {
- pstate->scriptptr = pstate->file.data + 3;
- pstate->scriptlen = pstate->file.len - 3;
- if (*(pstate->scriptptr - 1) == ISO_colon)
+ if (*pstate->file.data == ISO_percent && *(pstate->file.data + 1) == ISO_bang)
{
- httpd_fs_open(pstate->scriptptr + 1, &pstate->file);
- send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
+ pstate->scriptptr = pstate->file.data + 3;
+ pstate->scriptlen = pstate->file.len - 3;
+ if (*(pstate->scriptptr - 1) == ISO_colon)
+ {
+ httpd_fs_open(pstate->scriptptr + 1, &pstate->file);
+ send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
+ }
+ else
+ {
+ httpd_cgi(pstate->scriptptr)(pstate, pstate->scriptptr);
+ }
+ next_scriptstate(pstate);
+
+ /* The script is over, so we reset the pointers and continue
+ * sending the rest of the file
+ */
+
+ pstate->file.data = pstate->scriptptr;
+ pstate->file.len = pstate->scriptlen;
}
else
{
- httpd_cgi(pstate->scriptptr)(pstate, pstate->scriptptr);
+ /* See if we find the start of script marker in the block of HTML
+ * to be sent
+ */
+
+ if (pstate->file.len > HTTPD_IOBUFFER_SIZE)
+ {
+ pstate->len = HTTPD_IOBUFFER_SIZE;
+ }
+ else
+ {
+ pstate->len = pstate->file.len;
+ }
+
+ if (*pstate->file.data == ISO_percent)
+ {
+ ptr = strchr(pstate->file.data + 1, ISO_percent);
+ }
+ else
+ {
+ ptr = strchr(pstate->file.data, ISO_percent);
+ }
+
+ if (ptr != NULL && ptr != pstate->file.data)
+ {
+ pstate->len = (int)(ptr - pstate->file.data);
+ if (pstate->len >= HTTPD_IOBUFFER_SIZE)
+ {
+ pstate->len = HTTPD_IOBUFFER_SIZE;
+ }
+ }
+ send(pstate->sockfd, pstate->file.data, pstate->len, 0);
+ pstate->file.data += pstate->len;
+ pstate->file.len -= pstate->len;
}
- next_scriptstate(pstate);
-
- /* The script is over, so we reset the pointers and continue
- sending the rest of the file */
- pstate->file.data = pstate->scriptptr;
- pstate->file.len = pstate->scriptlen;
-
- } else {
- /* See if we find the start of script marker in the block of HTML
- to be sent */
-
- if (pstate->file.len > HTTPD_IOBUFFER_SIZE) {
- pstate->len = HTTPD_IOBUFFER_SIZE;
- } else {
- pstate->len = pstate->file.len;
- }
-
- if (*pstate->file.data == ISO_percent) {
- ptr = strchr(pstate->file.data + 1, ISO_percent);
- } else {
- ptr = strchr(pstate->file.data, ISO_percent);
- }
- if (ptr != NULL &&
- ptr != pstate->file.data) {
- pstate->len = (int)(ptr - pstate->file.data);
- if (pstate->len >= HTTPD_IOBUFFER_SIZE) {
- pstate->len = HTTPD_IOBUFFER_SIZE;
- }
- }
- send(pstate->sockfd, pstate->file.data, pstate->len, 0);
- pstate->file.data += pstate->len;
- pstate->file.len -= pstate->len;
}
- }
}
static int send_headers(struct httpd_state *pstate, const char *statushdr)
@@ -259,6 +276,7 @@ static inline int httpd_cmd(struct httpd_state *pstate)
recvlen = recv(pstate->sockfd, pstate->ht_buffer, HTTPD_IOBUFFER_SIZE, 0);
if (recvlen < 0)
{
+ dbg("recv failed: %d\n", errno);
return ERROR;
}
httpd_dumpbuffer(pstate, recvlen);
@@ -267,6 +285,7 @@ static inline int httpd_cmd(struct httpd_state *pstate)
if (strncmp(pstate->ht_buffer, http_get, 4) != 0)
{
+ dbg("Unsupported command\n");
return ERROR;
}
@@ -274,6 +293,7 @@ static inline int httpd_cmd(struct httpd_state *pstate)
if (pstate->ht_buffer[4] != ISO_slash)
{
+ dbg("Missing path\n");
return ERROR;
}
else if (pstate->ht_buffer[5] == ISO_space)
@@ -304,12 +324,14 @@ static inline int httpd_cmd(struct httpd_state *pstate)
*
****************************************************************************/
-static int httpd_handler(int argc, char *argv[])
+static void *httpd_handler(void *arg)
{
struct httpd_state *pstate = (struct httpd_state *)malloc(sizeof(struct httpd_state));
- int sockfd = (int)argv[1] - 1;
+ int sockfd = (int)arg;
int ret = ERROR;
+ dbg("Started, sd=%d\n", sockfd);
+
/* Verify that the state structure was successfully allocated */
if (pstate)
@@ -335,7 +357,9 @@ static int httpd_handler(int argc, char *argv[])
/* Exit the task */
- return 0;
+ dbg("Exitting\n");
+ close(sockfd);
+ pthread_exit(NULL);
}
/****************************************************************************
diff --git a/nuttx/sched/task_create.c b/nuttx/sched/task_create.c
index ee0e86c6e..96df1ae60 100644
--- a/nuttx/sched/task_create.c
+++ b/nuttx/sched/task_create.c
@@ -130,7 +130,7 @@ int task_create(const char *name, int priority,
/* Associate file descriptors with the new task */
-#if CONFIG_NFILE_DESCRIPTORS > 0
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
if (sched_setuptaskfiles(tcb) != OK)
{
sched_releasetcb(tcb);