summaryrefslogtreecommitdiff
path: root/nuttx/net
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-09-02 21:58:35 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-09-02 21:58:35 +0000
commit9a272c38fb40781171f7b4d054430f2c0be730c0 (patch)
tree892d21bc1008301a5f07a8634cf5cb227f563dc6 /nuttx/net
parent8e6fadad87d3220628d412fee845ad0b0cfb697f (diff)
downloadpx4-nuttx-9a272c38fb40781171f7b4d054430f2c0be730c0.tar.gz
px4-nuttx-9a272c38fb40781171f7b4d054430f2c0be730c0.tar.bz2
px4-nuttx-9a272c38fb40781171f7b4d054430f2c0be730c0.zip
Implements basic TCP connection logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@326 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/net')
-rw-r--r--nuttx/net/Makefile1
-rw-r--r--nuttx/net/bind.c25
-rw-r--r--nuttx/net/connect.c74
-rw-r--r--nuttx/net/net_internal.h2
-rw-r--r--nuttx/net/socket.c16
-rw-r--r--nuttx/net/uip/Make.defs2
-rw-r--r--nuttx/net/uip/uip-internal.h86
-rw-r--r--nuttx/net/uip/uip-tcpconn.c405
-rw-r--r--nuttx/net/uip/uip-udpconn.c170
-rw-r--r--nuttx/net/uip/uip.c565
10 files changed, 998 insertions, 348 deletions
diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile
index 9caa4f8ff..25b5c46df 100644
--- a/nuttx/net/Makefile
+++ b/nuttx/net/Makefile
@@ -34,6 +34,7 @@
############################################################
-include $(TOPDIR)/Make.defs
+CFLAGS += -I./uip
MKDEP = $(TOPDIR)/tools/mkdeps.sh
diff --git a/nuttx/net/bind.c b/nuttx/net/bind.c
index daeb70a87..332214d33 100644
--- a/nuttx/net/bind.c
+++ b/nuttx/net/bind.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * bind.c
+ * net/bind.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@@ -82,9 +82,14 @@
*
****************************************************************************/
-int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
FAR struct socket *psock = sockfd_socket(sockfd);
+#ifdef CONFIG_NET_IPv6
+ FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr;
+#else
+ FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr;
+#endif
int err;
/* Verify that the sockfd corresponds to valid, allocated socket */
@@ -95,16 +100,28 @@ int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
goto errout;
}
+ /* Verify that a valid address has been provided */
+
+#ifdef CONFIG_NET_IPv6
+ if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6))
+#else
+ if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
+#endif
+ {
+ err = EBADF;
+ goto errout;
+ }
+
/* Perform the binding depending on the protocol type */
switch (psock->s_type)
{
case SOCK_STREAM:
- /* Put TCP/IP binding logic here */
+#warning Put TCP/IP binding logic here
break;
#ifdef CONFIG_NET_UDP
case SOCK_DGRAM:
- /* Put UDP binding logic here */
+#warning Put UDP binding logic here
break;
#endif
default:
diff --git a/nuttx/net/connect.c b/nuttx/net/connect.c
index 5cff6210e..2fcb8bc79 100644
--- a/nuttx/net/connect.c
+++ b/nuttx/net/connect.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * connect.c
+ * net/connect.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@@ -44,6 +44,8 @@
#include <sys/socket.h>
#include <errno.h>
+#include "net_internal.h"
+
/****************************************************************************
* Global Functions
****************************************************************************/
@@ -117,9 +119,75 @@
*
****************************************************************************/
-int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
- *get_errno_ptr() = ENOSYS;
+ FAR struct socket *psock = sockfd_socket(sockfd);
+#ifdef CONFIG_NET_IPv6
+ FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr;
+#else
+ FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr;
+#endif
+ int err;
+
+ /* Verify that the sockfd corresponds to valid, allocated socket */
+
+ if (!psock || psock->s_crefs <= 0)
+ {
+ err = EBADF;
+ goto errout;
+ }
+
+ /* Verify that a valid address has been provided */
+
+#ifdef CONFIG_NET_IPv6
+ if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6))
+#else
+ if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
+#endif
+ {
+ err = EBADF;
+ goto errout;
+ }
+
+ /* Perform the binding depending on the protocol type */
+ switch (psock->s_type)
+ {
+ case SOCK_STREAM:
+ {
+ int ret = uip_tcpconnect(psock->s_conn, inaddr);
+ if (ret < 0)
+ {
+ err = -ret;
+ goto errout;
+ }
+ }
+ break;
+
+#ifdef CONFIG_NET_UDP
+ case SOCK_DGRAM:
+#warning Put UDP connect logic here
+#if 0
+ {
+ int ret = uip_udpconnect(psock->s_conn, inaddr);
+ if (ret < 0)
+ {
+ err = -ret;
+ goto errout;
+ }
+ }
+ break;
+#endif
+#endif
+ default:
+ err = EBADF;
+ goto errout;
+ }
+
+ err = ENOSYS;
+ /*return OK;*/
+
+errout:
+ *get_errno_ptr() = err;
return ERROR;
}
diff --git a/nuttx/net/net_internal.h b/nuttx/net/net_internal.h
index d45dcef7d..2bc7e4d7d 100644
--- a/nuttx/net/net_internal.h
+++ b/nuttx/net/net_internal.h
@@ -45,6 +45,8 @@
#include <nuttx/net.h>
+#include "net_internal.h"
+
/****************************************************************************
* Definitions
****************************************************************************/
diff --git a/nuttx/net/socket.c b/nuttx/net/socket.c
index 8fe3e395a..ad3ef1e92 100644
--- a/nuttx/net/socket.c
+++ b/nuttx/net/socket.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * socket.c
+ * net/socket.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@@ -129,15 +129,25 @@ int socket(int domain, int type, int protocol)
/* Initialize the socket structure */
-#ifdef CONFIG_NET_UDP
psock = sockfd_socket(sockfd);
if (psock)
{
/* Save the protocol type */
psock->s_type = type;
+
+ /* Allocate a TCP connection structure */
+
+ psock->s_conn = uip_tcpalloc();
+ if (!psock->s_conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ sockfd_release(sockfd);
+ err = ENFILE;
+ goto errout;
+ }
}
-#endif
return sockfd;
diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs
index 85d61d0d9..716682547 100644
--- a/nuttx/net/uip/Make.defs
+++ b/nuttx/net/uip/Make.defs
@@ -34,5 +34,5 @@
############################################################################
UIP_ASRCS =
-UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c uip-wait.c
+UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c uip-tcpconn.c uip-wait.c
diff --git a/nuttx/net/uip/uip-internal.h b/nuttx/net/uip/uip-internal.h
new file mode 100644
index 000000000..987b650c7
--- /dev/null
+++ b/nuttx/net/uip/uip-internal.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * net/uip/uip-internal.h
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * This logic was leveraged from uIP which also has a BSD-style license:
+ *
+ * Author Adam Dunkels <adam@dunkels.com>
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __UIP_INTERNAL_H
+#define __UIP_INTERNAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+/****************************************************************************
+ * Public Macro Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* g_tcp_sequence[] is used to generate TCP sequence numbers */
+
+extern uint8 g_tcp_sequence[4];
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/* Defined in uip_tcpconn.c *************************************************/
+
+EXTERN void uip_tcpinit(void);
+EXTERN struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf);
+EXTERN void uip_tcpnextsequence(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UIP_INTERNAL_H */
diff --git a/nuttx/net/uip/uip-tcpconn.c b/nuttx/net/uip/uip-tcpconn.c
new file mode 100644
index 000000000..c877de2c4
--- /dev/null
+++ b/nuttx/net/uip/uip-tcpconn.c
@@ -0,0 +1,405 @@
+/****************************************************************************
+ * uip_tcpbind.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 Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Compilation Switches
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#ifdef CONFIG_NET
+
+#include <sys/types.h>
+#include <string.h>
+#include <arch/irq.h>
+
+#include <net/uip/uipopt.h>
+#include <net/uip/uip.h>
+#include <net/uip/uip-arch.h>
+
+#include "uip-internal.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* g_tcp_sequence[] is used to generate TCP sequence numbers */
+
+uint8 g_tcp_sequence[4];
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The array containing all uIP connections. */
+
+static struct uip_conn g_tcp_connections[UIP_CONNS];
+
+/* Last port used by a TCP connection connection. */
+
+static uint16 g_last_tcp_port;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Given a port number, find the socket bound to the port number.
+ * Primary use: to determine if a port number is available.
+ */
+
+static struct uip_conn *uip_find_conn(uint16 portno)
+{
+ struct uip_conn *conn;
+ int i;
+
+ /* Check if this port number is already in use, and if so try to find
+ * another one.
+ */
+
+ for (i = 0; i < UIP_CONNS; i++)
+ {
+ conn = &g_tcp_connections[i];
+ if (conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(g_last_tcp_port))
+ {
+ /* The portnumber is in use */
+
+ return conn;
+ }
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uip_tcpinit()
+ *
+ * Description:
+ * Initialize the TCP/IP connection structures. Called only from the UIP
+ * layer.
+ *
+ ****************************************************************************/
+
+void uip_tcpinit(void)
+{
+ int i;
+ for (i = 0; i < UIP_CONNS; i++)
+ {
+ g_tcp_connections[i].tcpstateflags = UIP_CLOSED;
+ }
+
+ g_last_tcp_port = 1024;
+}
+
+/****************************************************************************
+ * Name: uip_tcpalloc()
+ *
+ * Description:
+ * Find a free TCP/IP connection structure and allocate it
+ * for use. This is normally something done by the implementation of the
+ * socket() API but is also called from the interrupt level when a TCP
+ * packet is received while "listening"
+ *
+ ****************************************************************************/
+
+struct uip_conn *uip_tcpalloc(void)
+{
+#if 0 /* Revisit */
+ struct uip_conn *oldest = NULL;
+#endif
+ irqstate_t flags;
+ unsigned int i;
+
+ /* Because this routine is called from both interrupt level and
+ * and from user level, we have not option but to disable interrupts
+ * while accessing g_tcp_connections[];
+ */
+
+ flags = irqsave();
+
+ /* Check if there are any available connections. */
+
+ for (i = 0; i < UIP_CONNS; i++)
+ {
+ /* First, check if any connections structures are marked as
+ * CLOSED in the table of pre-allocated connection structures.
+ */
+
+ if (g_tcp_connections[i].tcpstateflags == UIP_CLOSED)
+ {
+ /* We found an unused structure. Mark as allocated, but not
+ * initialized.
+ */
+
+ memset(&g_tcp_connections[i], 0, sizeof(struct uip_conn));
+ g_tcp_connections[i].tcpstateflags = UIP_ALLOCATED;
+
+ irqrestore(flags);
+ return &g_tcp_connections[i];
+ }
+
+#if 0 /* Revisit */
+ /* As a fallback, check for connection structures in the TIME_WAIT
+ * state. If no CLOSED connections are found, then take the oldest
+ */
+
+ if (g_tcp_connections[i].tcpstateflags == UIP_TIME_WAIT)
+ {
+ if (!oldest || g_tcp_connections[i].timer > oldest->timer)
+ {
+ oldest = &g_tcp_connections[i];
+ }
+ }
+ }
+ return oldest;
+#else
+ }
+
+ irqrestore(flags);
+ return NULL;
+#endif
+}
+
+/****************************************************************************
+ * Name: uip_tcpfree()
+ *
+ * Description:
+ * Free a connection structure that is no longer in use. This should be
+ * done by the implementation of close()
+ *
+ ****************************************************************************/
+
+void uip_tcpfree(struct uip_conn *conn)
+{
+ /* this action is atomic and should require no special protetion */
+
+ conn->tcpstateflags = UIP_CLOSED;
+}
+
+/****************************************************************************
+ * Name: uip_tcpactive()
+ *
+ * Description:
+ * Find a connection structure that is the appropriate
+ * connection to be used withi the provided TCP/IP header
+ *
+ * Assumptions:
+ * This function is called from UIP logic at interrupt level
+ *
+ ****************************************************************************/
+
+struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf)
+{
+ struct uip_conn *conn;
+ for (conn = g_tcp_connections; conn <= &g_tcp_connections[UIP_CONNS - 1]; conn++)
+ {
+ /* Find an open connection matching the tcp input */
+
+ if (conn->tcpstateflags != UIP_CLOSED &&
+ buf->destport == conn->lport && buf->srcport == conn->rport &&
+ uip_ipaddr_cmp(buf->srcipaddr, conn->ripaddr))
+ {
+ return conn;
+ }
+ }
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: uip_tcppoll()
+ *
+ * Description:
+ * 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 by the UIP
+ * device driver when the periodic uIP timer goes off. It should be
+ * called for every connection, regardless of whether they are open of
+ * closed.
+ *
+ * Assumptions:
+ * This function is called from the CAN device driver may be called from
+ * the timer interrupt/watchdog handle level.
+ *
+ ****************************************************************************/
+
+void uip_tcppoll(unsigned int conn)
+{
+ uip_conn = &g_tcp_connections[conn];
+ uip_interrupt(UIP_TIMER);
+}
+
+/****************************************************************************
+ * Name: uip_tcpactive()
+ *
+ * Description:
+ * Increment the TCP/IP sequence number
+ *
+ * Assumptions:
+ * This function is called from the interrupt level
+ *
+ ****************************************************************************/
+
+void uip_tcpnextsequence(void)
+{
+ /* This inplements a byte-by-byte big-endian increment */
+
+ if (++g_tcp_sequence[3] == 0)
+ {
+ if (++g_tcp_sequence[2] == 0)
+ {
+ if (++g_tcp_sequence[1] == 0)
+ {
+ ++g_tcp_sequence[0];
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: uip_tcpbind()
+ *
+ * Description:
+ * This function implements the UIP specific parts of the standard TCP
+ * bind() operation.
+ *
+ * Assumptions:
+ * This function is called from normal user level code.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IPv6
+int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr)
+#else
+int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr)
+#endif
+{
+#warning "Need to implement bind logic"
+ return ERROR;
+}
+
+/****************************************************************************
+ * Name: uip_tcpbind()
+ *
+ * Description:
+ * This function implements the UIP specific parts of the standard
+ * TCP connect() operation: It connects to a remote host using TCP.
+ *
+ * This function is used to start a new connection to the specified
+ * port on the specied host. It uses the connection structure that was
+ * allocated by a preceding socket() call. It 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_tcpconnect().
+ *
+ * Assumptions:
+ * This function is called from normal user level code.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IPv6
+int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in6 *addr )
+#else
+int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr )
+#endif
+{
+ uint16 port;
+ int i;
+
+ /* If the TCP port has not alread been bound to a local port, then select
+ * one now.
+ */
+
+ port = ntohs(conn->lport);
+ if (port == 0)
+ {
+ /* No local port assigned. Loop until we find a valid listen port number\
+ * that is not being used by any other connection.
+ */
+
+ do
+ {
+ /* Guess that the next available port number will be the one after
+ * the last port number assigned.
+ */
+#warning "This need protection from other threads and from interrupts"
+ port = ++g_last_tcp_port;
+
+ /* Make sure that the port number is within range */
+
+ if (g_last_tcp_port >= 32000)
+ {
+ g_last_tcp_port = 4096;
+ }
+ }
+ while (uip_find_conn(g_last_tcp_port));
+ }
+
+ /* Initialize and return the connection structure, bind it to the port number */
+
+ conn->tcpstateflags = UIP_SYN_SENT;
+
+ conn->snd_nxt[0] = g_tcp_sequence[0];
+ conn->snd_nxt[1] = g_tcp_sequence[1];
+ conn->snd_nxt[2] = g_tcp_sequence[2];
+ conn->snd_nxt[3] = g_tcp_sequence[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; /* Initial value of the RTT variance. */
+ conn->lport = htons(port);
+
+ /* The sockaddr port is 16 bits and already in network order */
+
+ conn->rport = addr->sin_port;
+
+ /* The sockaddr address is 32-bits in network order. */
+
+ uip_ipaddr_copy(&conn->ripaddr, addr->sin_addr.s_addr);
+ return OK;
+}
+
+#endif /* CONFIG_NET */
diff --git a/nuttx/net/uip/uip-udpconn.c b/nuttx/net/uip/uip-udpconn.c
new file mode 100644
index 000000000..3b7f06fa6
--- /dev/null
+++ b/nuttx/net/uip/uip-udpconn.c
@@ -0,0 +1,170 @@
+/************************************************************
+ * uip-udpconn.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 Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Compilation Switches
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP)
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+struct uip_udp_conn *uip_udpalloc(void);
+void uip_udpfree(struct uip_udp_conn *conn);
+
+#ifdef CONFIG_NET_IPv6
+int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr);
+#else
+int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr);
+#endif
+
+#ifdef CONFIG_NET_IPv6
+int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr )
+#else
+int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr)
+#endif
+{
+ uint16 ipaddr[2];
+
+ if (pdhcpc->state == STATE_INITIAL)
+ {
+ uip_ipaddr(ipaddr, 0,0,0,0);
+ uip_sethostaddr(ipaddr);
+ }
+ return OK;
+}
+
+/* Set up a new UDP connection.
+ *
+ * This function sets up a new UDP connection. The function will
+ * automatically allocate an unused local port for the new
+ * connection. However, another port can be chosen by using the
+ * uip_udp_bind() call, after the uip_udp_new() function has been
+ * called.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t addr;
+ * struct uip_udp_conn *c;
+ *
+ * uip_ipaddr(&addr, 192,168,2,1);
+ * c = uip_udp_new(&addr, HTONS(12345));
+ * if(c != NULL) {
+ * uip_udp_bind(c, HTONS(12344));
+ * }
+ *
+ * ripaddr The IP address of the remote host.
+ *
+ * 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(uip_ipaddr_t *ripaddr, uint16 rport)
+{
+ struct uip_udp_conn *conn;
+ int i;
+
+ /* Find an unused local port number. Loop until we find a valid listen port
+ * number that is not being used by any other connection.
+ */
+
+ do
+ {
+ /* Guess that the next available port number will be the one after
+ * the last port number assigned.
+ */
+
+ ++g_last_udp_port;
+
+ /* Make sure that the port number is within range */
+ if (g_last_udp_port >= 32000)
+ {
+ g_last_udp_port = 4096;
+ }
+ }
+ while (uip_find_udp_conn(g_last_udp_port));
+
+ /* Now find an available UDP connection structure */
+
+ conn = 0;
+ for (i = 0; i < UIP_UDP_CONNS; i++)
+ {
+ if (uip_udp_conns[c].lport == 0)
+ {
+ conn = &uip_udp_conns[c];
+ break;
+ }
+ }
+
+ /* Return an error if no connection is available */
+
+ if (conn == 0)
+ {
+ return 0;
+ }
+
+ /* Initialize and return the connection structure, bind it to the port number */
+
+ conn->lport = HTONS(g_last_udp_port);
+ conn->rport = rport;
+
+ if (ripaddr == NULL)
+ {
+ memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
+ }
+ else
+ {
+ uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+ }
+
+ conn->ttl = UIP_TTL;
+
+ return conn;
+}
+
+#endif /* CONFIG_NET */
diff --git a/nuttx/net/uip/uip.c b/nuttx/net/uip/uip.c
index 7fa2e3b7e..830f34551 100644
--- a/nuttx/net/uip/uip.c
+++ b/nuttx/net/uip/uip.c
@@ -93,6 +93,8 @@ extern void uip_log(char *msg);
# define UIP_LOG(m)
#endif /* UIP_LOGGING == 1 */
+#include "uip-internal.h"
+
/****************************************************************************
* Definitions
****************************************************************************/
@@ -175,11 +177,9 @@ uint16 uip_flags; /* The uip_flags variable is used for communica
* program. */
struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */
-struct uip_conn uip_conns[UIP_CONNS];
- /* The uip_conns array holds all TCP connections. */
uint16 uip_listenports[UIP_LISTENPORTS];
/* The uip_listenports list all currently listning ports. */
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_UDP
struct uip_udp_conn *uip_udp_conn;
struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
#endif /* CONFIG_NET_UDP */
@@ -222,11 +222,10 @@ struct uip_eth_addr uip_ethaddr = {{ 0,0,0,0,0,0 }};
static uint16 ipid; /* Ths ipid variable is an increasing number that is
* used for the IP ID field. */
-static uint8 iss[4]; /* The iss variable is used for the TCP initial
- * sequence number. */
-
-static uint16 lastport; /* Keeps track of the last port used for a new
+#ifdef CONFIG_NET_UDP
+static uint16 g_last_udp_port; /* Keeps track of the last port used for a new
* connection. */
+#endif
/* Temporary variables. */
static uint8 c, opt;
@@ -236,38 +235,6 @@ static uint16 tmp16;
* Private Functions
****************************************************************************/
-#if !UIP_ARCH_ADD32
-static void uip_add32(uint8 *op32, uint16 op16)
-{
- 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_acc32[3] < (op16 & 0xff))
- {
- ++uip_acc32[2];
- if (uip_acc32[2] == 0)
- {
- ++uip_acc32[1];
- if (uip_acc32[1] == 0)
- {
- ++uip_acc32[0];
- }
- }
- }
-}
-#endif /* UIP_ARCH_ADD32 */
-
#if !UIP_ARCH_CHKSUM
static uint16 chksum(uint16 sum, const uint8 *data, uint16 len)
{
@@ -340,34 +307,7 @@ static uint16 uip_icmp6chksum(void)
#endif /* UIP_ARCH_CHKSUM */
-/* Given a port number, find the socket bound to the port number.
- * Primary use: to determine if a port number is available.
- */
-
-struct uip_conn *uip_find_conn( uint16 portno )
-{
- struct uip_conn *conn;
- int i;
-
- /* Check if this port number is already in use, and if so try to find
- * another one.
- */
-
- for (i = 0; i < UIP_CONNS; i++)
- {
- conn = &uip_conns[i];
- if (conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport))
- {
- /* The portnumber is in use */
-
- return conn;
- }
- }
-
- return NULL;
-}
-
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_UDP
struct uip_udp_conn *uip_find_udp_conn( uint16 portno )
{
struct uip_udp_conn *conn;
@@ -375,7 +315,7 @@ struct uip_udp_conn *uip_find_udp_conn( uint16 portno )
for (i = 0; i < UIP_UDP_CONNS; i++)
{
- if (uip_udp_conns[i].lport == htons(lastport))
+ if (uip_udp_conns[i].lport == htons(g_last_udp_port))
{
return conn;
}
@@ -398,6 +338,38 @@ void uip_setipid(uint16 id)
/* Calculate the Internet checksum over a buffer. */
+#if !UIP_ARCH_ADD32
+void uip_add32(uint8 *op32, uint16 op16)
+{
+ 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_acc32[3] < (op16 & 0xff))
+ {
+ ++uip_acc32[2];
+ if (uip_acc32[2] == 0)
+ {
+ ++uip_acc32[1];
+ if (uip_acc32[1] == 0)
+ {
+ ++uip_acc32[0];
+ }
+ }
+ }
+}
+#endif /* UIP_ARCH_ADD32 */
+
#if !UIP_ARCH_CHKSUM
uint16 uip_chksum(uint16 *data, uint16 len)
{
@@ -426,7 +398,7 @@ uint16 uip_tcpchksum(void)
/* Calculate the UDP checksum of the packet in uip_buf and uip_appdata. */
- #ifdef CONFIG_NET_UDP_CHECKSUMS
+#ifdef CONFIG_NET_UDP_CHECKSUMS
uint16 uip_udpchksum(void)
{
return upper_layer_chksum(UIP_PROTO_UDP);
@@ -441,17 +413,19 @@ void uip_init(void)
uip_listenports[c] = 0;
}
- for (c = 0; c < UIP_CONNS; ++c)
- {
- uip_conns[c].tcpstateflags = UIP_CLOSED;
- }
- lastport = 1024;
+ /* Initialize the TCP/IP connection structures */
+
+ uip_tcpinit();
+
+ /* Initialize the UDP connection structures */
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_UDP
for (c = 0; c < UIP_UDP_CONNS; ++c)
{
uip_udp_conns[c].lport = 0;
}
+
+ g_last_udp_port = 1024;
#endif /* CONFIG_NET_UDP */
/* IPv4 initialization. */
@@ -460,83 +434,6 @@ void uip_init(void)
#endif /* UIP_FIXEDADDR */
}
-struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16 rport)
-{
- struct uip_conn *conn, *cconn;
- int i;
-
- /* Find an unused local port number. Loop until we find a valid listen port
- * number that is not being used by any other connection.
- */
-
- do
- {
- /* Guess that the next available port number will be the one after
- * the last port number assigned.
- */
-
- ++lastport;
-
- /* Make sure that the port number is within range */
- if (lastport >= 32000)
- {
- lastport = 4096;
- }
- }
- while (uip_find_conn(lastport));
-
- /* Now find an available connection structure */
-
- conn = 0;
- for (i = 0; i < UIP_CONNS; i++)
- {
- cconn = &uip_conns[i];
- if (cconn->tcpstateflags == UIP_CLOSED)
- {
- conn = cconn;
- break;
- }
-
- if (cconn->tcpstateflags == UIP_TIME_WAIT)
- {
- if (conn == 0 || cconn->timer > conn->timer)
- {
- conn = cconn;
- }
- }
- }
-
- /* Return an error if no connection is available */
-
- if (conn == 0)
- {
- return 0;
- }
-
- /* Initialize and return the connection structure, bind it to the port number */
-
- conn->tcpstateflags = UIP_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; /* Initial value of the RTT variance. */
- conn->lport = htons(lastport);
- conn->rport = rport;
- uip_ipaddr_copy(&conn->ripaddr, ripaddr);
-
- return conn;
-}
-
#ifdef CONFIG_NET_UDP
struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport)
{
@@ -553,15 +450,15 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport)
* the last port number assigned.
*/
- ++lastport;
+ ++g_last_udp_port;
/* Make sure that the port number is within range */
- if (lastport >= 32000)
+ if (g_last_udp_port >= 32000)
{
- lastport = 4096;
+ g_last_udp_port = 4096;
}
}
- while (uip_find_udp_conn(lastport));
+ while (uip_find_udp_conn(g_last_udp_port));
/* Now find an available UDP connection structure */
@@ -584,7 +481,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport)
/* Initialize and return the connection structure, bind it to the port number */
- conn->lport = HTONS(lastport);
+ conn->lport = HTONS(g_last_udp_port);
conn->rport = rport;
if (ripaddr == NULL)
@@ -616,15 +513,17 @@ void uip_unlisten(uint16 port)
void uip_listen(uint16 port)
{
- for (c = 0; c < UIP_LISTENPORTS; ++c) {
- if (uip_listenports[c] == 0) {
- uip_listenports[c] = port;
- return;
+ for (c = 0; c < UIP_LISTENPORTS; ++c)
+ {
+ if (uip_listenports[c] == 0)
+ {
+ uip_listenports[c] = port;
+ return;
+ }
}
- }
}
-/* XXX: IP fragment reassembly: not well-tested. */
+/* IP fragment reassembly: not well-tested. */
#if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6)
#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
@@ -644,113 +543,133 @@ static uint8 uip_reass(void)
uint16 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, UIP_IPH_LEN);
- uip_reasstmr = UIP_REASS_MAXAGE;
- uip_reassflags = 0;
- /* Clear the bitmap. */
- memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
- }
+ * write the IP header of the fragment into the reassembly
+ * buffer. The timer is updated with the maximum age.
+ */
- /* 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;
+ if (uip_reasstmr == 0)
+ {
+ memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
+ uip_reasstmr = UIP_REASS_MAXAGE;
+ uip_reassflags = 0;
+
+ /* Clear the bitmap. */
+ memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
}
- /* Copy the fragment into the reassembly buffer, at the right
- offset. */
- memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
- (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
- len);
+ /* 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[UIP_IPH_LEN + 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 (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];
- if ((BUF->ipoffset[0] & IP_MF) == 0) {
- uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
- uip_reasslen = offset + len;
- }
+ }
+ else
+ {
+ /* If the two endpoints are in different bytes, we update the bytes
+ * in the endpoints and fill the stuff inbetween with 0xff.
+ */
- /* 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;
- }
+ 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];
}
- /* Check the last byte in the bitmap. It should contain just the
- right amount of bits. */
- if (uip_reassbitmap[uip_reasslen / (8 * 8)] !=
- (uint8)~bitmap_bits[uip_reasslen / 8 & 7]) {
- goto nullreturn;
+ /* 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;
}
- /* 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;
- }
+ /* 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)] != (uint8)~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:
+nullreturn:
return 0;
}
#endif /* UIP_REASSEMBLY */
@@ -768,7 +687,7 @@ void uip_interrupt(uint8 flag)
{
register struct uip_conn *uip_connr = uip_conn;
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_UDP
if (flag == UIP_UDP_SEND_CONN)
{
goto udp_send;
@@ -805,22 +724,13 @@ void uip_interrupt(uint8 flag)
}
#endif /* UIP_REASSEMBLY */
- /* Increase the initial sequence number */
+ /* Increase the TCP sequence number */
- if (++iss[3] == 0)
- {
- if (++iss[2] == 0)
- {
- if (++iss[1] == 0)
- {
- ++iss[0];
- }
- }
- }
+ uip_tcpnextsequence();
/* Reset the length variables. */
- uip_len = 0;
+ uip_len = 0;
uip_slen = 0;
/* Check if the connection is in a state in which we simply wait
@@ -935,7 +845,7 @@ void uip_interrupt(uint8 flag)
goto drop;
}
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_UDP
if (flag == UIP_UDP_TIMER)
{
if (uip_udp_conn->lport != 0)
@@ -1105,7 +1015,7 @@ void uip_interrupt(uint8 flag)
goto tcp_input;
}
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_UDP
if (BUF->proto == UIP_PROTO_UDP)
{
goto udp_input;
@@ -1247,14 +1157,14 @@ void uip_interrupt(uint8 flag)
#endif /* !CONFIG_NET_IPv6 */
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_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. */
- #ifdef CONFIG_NET_UDP_CHECKSUMS
+#ifdef CONFIG_NET_UDP_CHECKSUMS
uip_len = uip_len - UIP_IPUDPH_LEN;
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
if (UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff)
@@ -1269,9 +1179,8 @@ void uip_interrupt(uint8 flag)
#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)
+
+ for (uip_udp_conn = &uip_udp_conns[0]; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; uip_udp_conn++)
{
/* If the local UDP port is non-zero, the connection is considered
* to be used. If so, the local port number is checked against the
@@ -1282,13 +1191,12 @@ void uip_interrupt(uint8 flag)
* address of the packet is checked.
*/
- if (uip_udp_conn->lport != 0 &&
- UDPBUF->destport == uip_udp_conn->lport &&
+ if (uip_udp_conn->lport != 0 && UDPBUF->destport == uip_udp_conn->lport &&
(uip_udp_conn->rport == 0 ||
- UDPBUF->srcport == uip_udp_conn->rport) &&
- (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
- uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
- uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr)))
+ UDPBUF->srcport == uip_udp_conn->rport) &&
+ (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
+ uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
+ uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr)))
{
goto udp_found;
}
@@ -1336,7 +1244,7 @@ void uip_interrupt(uint8 flag)
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
- #ifdef CONFIG_NET_UDP_CHECKSUMS
+#ifdef CONFIG_NET_UDP_CHECKSUMS
/* Calculate UDP checksum. */
UDPBUF->udpchksum = ~(uip_udpchksum());
if (UDPBUF->udpchksum == 0)
@@ -1357,30 +1265,27 @@ void uip_interrupt(uint8 flag)
if (uip_tcpchksum() != 0xffff)
{
/* Compute and check the TCP checksum. */
+
UIP_STAT(++uip_stat.tcp.drop);
UIP_STAT(++uip_stat.tcp.chkerr);
UIP_LOG("tcp: bad checksum.");
goto drop;
}
- /* Demultiplex this segment. */
- /* First check any active connections. */
- for (uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
- ++uip_connr)
+ /* Demultiplex this segment. First check any active connections. */
+
+ uip_connr = uip_tcpactive(BUF);
+ if (uip_connr)
{
- if (uip_connr->tcpstateflags != UIP_CLOSED &&
- BUF->destport == uip_connr->lport &&
- BUF->srcport == uip_connr->rport &&
- uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr))
- {
- goto found;
- }
+ 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. */
+ * 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_CTL) != TCP_SYN)
{
goto reset;
@@ -1455,57 +1360,43 @@ void uip_interrupt(uint8 flag)
goto tcp_send_noconn;
/* This label will be jumped to if we matched the incoming packet
- with a connection in LISTEN. In that case, we should create a new
- connection and send a SYNACK in return. */
- 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. 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 == UIP_CLOSED)
- {
- uip_connr = &uip_conns[c];
- break;
- }
- if (uip_conns[c].tcpstateflags == UIP_TIME_WAIT)
- {
- if (uip_connr == 0 || uip_conns[c].timer > uip_connr->timer)
- {
- uip_connr = &uip_conns[c];
- }
- }
- }
+ * with a connection in LISTEN. In that case, we should create a new
+ * connection and send a SYNACK in return.
+ */
- if (uip_connr == 0)
+found_listen:
+
+ /* First allocate a new connection structure */
+
+ uip_connr = uip_tcpalloc();
+ if (!uip_connr)
{
/* 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. */
+ * 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;
- }
+ UIP_LOG("tcp: found no unused connections.");
+ goto drop;
+ }
uip_conn = uip_connr;
/* Fill in the necessary fields for the new connection. */
- uip_connr->rto = uip_connr->timer = UIP_RTO;
- uip_connr->sa = 0;
- uip_connr->sv = 4;
- uip_connr->nrtx = 0;
+
+ 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_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
uip_connr->tcpstateflags = UIP_SYN_RCVD;
- 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->snd_nxt[0] = g_tcp_sequence[0];
+ uip_connr->snd_nxt[1] = g_tcp_sequence[1];
+ uip_connr->snd_nxt[2] = g_tcp_sequence[2];
+ uip_connr->snd_nxt[3] = g_tcp_sequence[3];
uip_connr->len = 1;
/* rcv_nxt should be the seqno from the incoming packet + 1. */
@@ -2119,7 +2010,7 @@ void uip_interrupt(uint8 flag)
BUF->tcpchksum = 0;
BUF->tcpchksum = ~(uip_tcpchksum());
- #ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_UDP
ip_send_nolen:
#endif /* CONFIG_NET_UDP */