diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-11-05 23:04:16 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-11-05 23:04:16 +0000 |
commit | 13a1d731ec51a27983bc9e6fcaa841607a090764 (patch) | |
tree | 93b32ce5f98ff118a21eb072cf111e164fd38686 | |
parent | 4cfb76d4d59acfdadc0f50527533b9c129edde41 (diff) | |
download | px4-nuttx-13a1d731ec51a27983bc9e6fcaa841607a090764.tar.gz px4-nuttx-13a1d731ec51a27983bc9e6fcaa841607a090764.tar.bz2 px4-nuttx-13a1d731ec51a27983bc9e6fcaa841607a090764.zip |
Basic TCP send functional
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@371 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/arch/sim/src/up_uipdriver.c | 53 | ||||
-rw-r--r-- | nuttx/configs/README.txt | 3 | ||||
-rw-r--r-- | nuttx/drivers/net/dm90x0.c | 84 | ||||
-rw-r--r-- | nuttx/examples/nettest/nettest-client.c | 2 | ||||
-rw-r--r-- | nuttx/examples/nettest/nettest-server.c | 51 | ||||
-rw-r--r-- | nuttx/include/net/uip/uip-arch.h | 124 | ||||
-rw-r--r-- | nuttx/include/net/uip/uip.h | 24 | ||||
-rw-r--r-- | nuttx/net/connect.c | 14 | ||||
-rw-r--r-- | nuttx/net/recvfrom.c | 31 | ||||
-rw-r--r-- | nuttx/net/send.c | 17 | ||||
-rw-r--r-- | nuttx/net/uip/Make.defs | 2 | ||||
-rw-r--r-- | nuttx/net/uip/uip-arp.c | 16 | ||||
-rw-r--r-- | nuttx/net/uip/uip-internal.h | 2 | ||||
-rw-r--r-- | nuttx/net/uip/uip-poll.c | 161 | ||||
-rw-r--r-- | nuttx/net/uip/uip-tcpconn.c | 67 | ||||
-rw-r--r-- | nuttx/net/uip/uip-udpconn.c | 37 | ||||
-rw-r--r-- | nuttx/net/uip/uip.c | 2150 | ||||
-rw-r--r-- | nuttx/netutils/telnetd/telnetd.c | 11 | ||||
-rw-r--r-- | nuttx/netutils/webclient/webclient.c | 16 |
19 files changed, 1619 insertions, 1246 deletions
diff --git a/nuttx/arch/sim/src/up_uipdriver.c b/nuttx/arch/sim/src/up_uipdriver.c index fbb8550de..3bd08c0b5 100644 --- a/nuttx/arch/sim/src/up_uipdriver.c +++ b/nuttx/arch/sim/src/up_uipdriver.c @@ -112,6 +112,25 @@ static inline int uip_comparemac(struct uip_eth_addr *paddr1, struct uip_eth_add } #endif +static int sim_uiptxpoll(struct uip_driver_s *dev) +{ + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (g_sim_dev.d_len > 0) + { + uip_arp_out(&g_sim_dev); + tapdev_send(g_sim_dev.d_buf, g_sim_dev.d_len); + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -182,39 +201,7 @@ void uipdriver_loop(void) else if (timer_expired(&g_periodic_timer)) { timer_reset(&g_periodic_timer); - for(i = 0; i < UIP_CONNS; i++) - { - uip_tcppoll(&g_sim_dev,i); - - /* If the above function invocation resulted in data that - * should be sent out on the network, the global variable - * d_len is set to a value > 0. - */ - - if (g_sim_dev.d_len > 0) - { - uip_arp_out(&g_sim_dev); - tapdev_send(g_sim_dev.d_buf, g_sim_dev.d_len); - } - } - -#ifdef CONFIG_NET_UDP - for(i = 0; i < UIP_UDP_CONNS; i++) - { - uip_udppoll(&g_sim_dev,i); - - /* If the above function invocation resulted in data that - * should be sent out on the network, the global variable - * d_len is set to a value > 0. - */ - - if (g_sim_dev.d_len > 0) - { - uip_arp_out(&g_sim_dev); - tapdev_send(g_sim_dev.d_buf, g_sim_dev.d_len); - } - } -#endif /* CONFIG_NET_UDP */ + uip_poll(&g_sim_dev, sim_uiptxpoll, UIP_TIMER); } sched_unlock(); } diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt index f07e4aaa5..0a1b42310 100644 --- a/nuttx/configs/README.txt +++ b/nuttx/configs/README.txt @@ -211,7 +211,8 @@ defconfig -- This is a configuration file similar to the Linux TCP/IP and UDP support via uIP 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_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors + per task/thread. CONFIG_NET_MAX_CONNECTIONS - 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 diff --git a/nuttx/drivers/net/dm90x0.c b/nuttx/drivers/net/dm90x0.c index 516d85663..63bde9c98 100644 --- a/nuttx/drivers/net/dm90x0.c +++ b/nuttx/drivers/net/dm90x0.c @@ -44,14 +44,7 @@ #include <nuttx/config.h> #if defined(CONFIG_NET) && defined(CONFIG_NET_DM90x0) -/* Force debug on for this file */ - -#undef CONFIG_DEBUG -#define CONFIG_DEBUG 1 -#undef CONFIG_DEBUG_VERBOSE -#define CONFIG_DEBUG_VERBOSE 1 - -/* Only one hardware interface supported at present (althought there are +/* Only one hardware interface supported at present (although there are * hooks throughout the design to that extending the support to multiple * interfaces should not be that difficult) */ @@ -382,7 +375,7 @@ static boolean dm9x_rxchecksumready(uint8); /* Common TX logic */ static int dm9x_transmit(struct dm9x_driver_s *dm9x); -static int dm9x_uiptxpoll(struct dm9x_driver_s *dm9x); +static int dm9x_uiptxpoll(struct uip_driver_s *dev); /* Interrupt handling */ @@ -816,7 +809,7 @@ static int dm9x_transmit(struct dm9x_driver_s *dm9x) * * Description: * The transmitter is available, check if uIP has any outgoing packets ready - * to send. This may be called: + * to send. This is a callback from uip_poll(). uip_poll() may be called: * * 1. When the preceding TX packet send is complete, * 2. When the preceding TX packet send timesout and the DM90x0 is reset @@ -832,67 +825,40 @@ static int dm9x_transmit(struct dm9x_driver_s *dm9x) * ****************************************************************************/ -static int dm9x_uiptxpoll(struct dm9x_driver_s *dm9x) +static int dm9x_uiptxpoll(struct uip_driver_s *dev) { - int i; - - for(i = 0; i < UIP_CONNS; i++) - { - uip_tcppoll(&dm9x->dev, i); - - /* If the above function invocation resulted in data that - * should be sent out on the network, the global variable - * d_len is set to a value > 0. - */ - - if (dm9x->dev.d_len > 0) - { - uip_arp_out(&dm9x->dev); - dm9x_transmit(dm9x); - - /* Check if there is room in the DM90x0 to hold another packet. In 100M mode, - * that can be 2 packets, otherwise it is a single packet. - */ + struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private; - if (dm9x->ntxpending > 1 || !dm9x->b100M) - { - return OK; - } - } - } + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ -#ifdef CONFIG_NET_UDP - for(i = 0; i < UIP_UDP_CONNS; i++) + if (dm9x->dev.d_len > 0) { - uip_udppoll(&dm9x->dev,i); + uip_arp_out(&dm9x->dev); + dm9x_transmit(dm9x); - /* If the above function invocation resulted in data that - * should be sent out on the network, the global variable - * d_len is set to a value > 0. + /* Check if there is room in the DM90x0 to hold another packet. In 100M mode, + * that can be 2 packets, otherwise it is a single packet. */ - if (dm9x->dev.d_len > 0) + if (dm9x->ntxpending > 1 || !dm9x->b100M) { - uip_arp_out(&dm9x->dev); - dm9x_transmit(dm9x); - - /* Check if there is room in the DM90x0 to hold another packet. In 100M mode, - * that can be 2 packets, otherwise it is a single packet. - */ + /* Returning a non-zero value will terminate the poll operation */ - if (dm9x->ntxpending > 1 || !dm9x->b100M) - { - return OK; - } + return 1; } } -#endif /* CONFIG_NET_UDP */ - return OK; + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; } /**************************************************************************** - * Function: dm9x_uiptxpoll + * Function: dm9x_receive * * Description: * An interrupt was received indicating the availability of a new RX packet @@ -1106,7 +1072,7 @@ static void dm9x_txdone(struct dm9x_driver_s *dm9x) /* Then poll uIP for new XMIT data */ - (void)dm9x_uiptxpoll(dm9x); + (void)uip_poll(&dm9x->dev, dm9x_uiptxpoll, UIP_POLL); } /**************************************************************************** @@ -1263,7 +1229,7 @@ static void dm9x_txtimeout(int argc, uint32 arg, ...) /* Then poll uIP for new XMIT data */ - (void)dm9x_uiptxpoll(dm9x); + (void)uip_poll(&dm9x->dev, dm9x_uiptxpoll, UIP_POLL); } /**************************************************************************** @@ -1307,7 +1273,7 @@ static void dm9x_polltimer(int argc, uint32 arg, ...) { /* If so, poll uIP for new XMIT data */ - (void)dm9x_uiptxpoll(dm9x); + (void)uip_poll(&dm9x->dev, dm9x_uiptxpoll, UIP_TIMER); } /* Setup the watchdog poll timer again */ diff --git a/nuttx/examples/nettest/nettest-client.c b/nuttx/examples/nettest/nettest-client.c index 98080d0c2..f352e3a85 100644 --- a/nuttx/examples/nettest/nettest-client.c +++ b/nuttx/examples/nettest/nettest-client.c @@ -93,7 +93,7 @@ void send_client(void) printf("client: connect failure: %d\n", errno); exit(1); } - printf("clilent: Connected\n"); + printf("client: Connected\n"); /* Initialize the buffer */ diff --git a/nuttx/examples/nettest/nettest-server.c b/nuttx/examples/nettest/nettest-server.c index 5ad4a0b01..a557b5a7d 100644 --- a/nuttx/examples/nettest/nettest-server.c +++ b/nuttx/examples/nettest/nettest-server.c @@ -61,7 +61,10 @@ void recv_server(void) socklen_t addrlen; int nbytesread; #ifndef CONFIG_NETTEST_PERFORMANCE + int totalbytesread; int nbytessent; + int ch; + int i; #endif int optval; @@ -130,19 +133,55 @@ void recv_server(void) } } #else - /* Receive and echo own message */ + /* Receive canned message */ - nbytesread = recv(acceptsd, buffer, 1024, 0); - if (nbytesread <= 0) + totalbytesread = 0; + while (totalbytesread < SENDSIZE) { - printf("server: recv failed: %d\n", errno); + printf("server: Reading...\n"); + nbytesread = recv(acceptsd, &buffer[totalbytesread], 1024 - totalbytesread, 0); + if (nbytesread <= 0) + { + printf("server: recv failed: %d\n", errno); + close(listensd); + close(acceptsd); + exit(-1); + } + + totalbytesread += nbytesread; + printf("server: Received %d of %d bytes\n", totalbytesread, SENDSIZE); + } + + /* Verify the message */ + + if (totalbytesread != SENDSIZE) + { + printf("server: Received %d / Expected %d bytes\n", totalbytesread, SENDSIZE); close(listensd); close(acceptsd); exit(-1); } - printf("server: Received %d bytes\n", nbytesread); - nbytessent = send(acceptsd, buffer, nbytesread, 0); + ch = 0x20; + for (i = 0; i < SENDSIZE; i++ ) + { + if (buffer[i] != ch) + { + printf("server: Byte %d is %02x / Expected %02x\n", i, buffer[i], ch); + close(listensd); + close(acceptsd); + exit(-1); + } + + if (++ch > 0x7e) + { + ch = 0x20; + } + } + + /* Then send the same data back to the client */ + + nbytessent = send(acceptsd, buffer, totalbytesread, 0); if (nbytessent <= 0) { printf("server: send failed: %d\n", errno); diff --git a/nuttx/include/net/uip/uip-arch.h b/nuttx/include/net/uip/uip-arch.h index 2c6720ab4..dd98925fc 100644 --- a/nuttx/include/net/uip/uip-arch.h +++ b/nuttx/include/net/uip/uip-arch.h @@ -65,14 +65,12 @@ * the macrose defined in this file. */ -#define UIP_DATA 1 /* Tells uIP that there is incoming data in the d_buf buffer. The +#define UIP_DATA 1 /* There is incoming data in the d_buf buffer. The * length of the data is stored in the field d_len. */ -#define UIP_TIMER 2 /* Tells uIP that the periodic timer has fired. */ -#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should be polled. */ -#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram should be constructed in the - * d_buf buffer. */ +#define UIP_TIMER 2 /* TCP periodic timer has fired */ +#define UIP_POLL_REQUEST 3 /* Poll TCP connection */ #ifdef CONFIG_NET_UDP -# define UIP_UDP_TIMER 5 +# define UIP_UDP_POLL 4 /* Poll UDP connection */ #endif /* CONFIG_NET_UDP */ /**************************************************************************** @@ -228,97 +226,77 @@ struct uip_driver_s * uip_input(); * if(dev->d_len > 0) { * uip_arp_out(); - * ethernet_devicedriver_send(); + * devicedriver_send(); * } * } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { * uip_arp_arpin(); * if(dev->d_len > 0) { - * ethernet_devicedriver_send(); + * devicedriver_send(); * } * } */ #define uip_input(dev) uip_interrupt(dev,UIP_DATA) -/* Periodic processing for a connection identified by its number. +/* Polling of connections. * - * This function does the necessary periodic processing (timers, - * polling) for a uIP TCP conneciton, and should be called when the - * periodic uIP timer goes off. It should be called for every - * connection, regardless of whether they are open of closed. + * This function will traverse each active uIP connection structure and + * perform uip_interrupt with the specified event. After each polling each + * active uIP connection structure, this function will call the provided + * callback function if the poll resulted in new data to be send. The poll + * will continue until all connections have been polled or until the user- + * suplied function returns a non-zero value (which is would do only if + * it cannot accept further write data). * - * When the function returns, it may have an outbound packet waiting - * for service in the uIP packet buffer, and if so the d_len field - * is set to a value larger than zero. The device driver - * should be called to send out the packet. + * This function should be called periodically with event == UIP_TIMER for + * periodic processing. This function may also be called with UIP_POLL to + * perform necessary periodic processing of TCP connections. * - * The ususal way of calling the function is through a for() loop like - * this: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. * - * for(i = 0; i < UIP_CONNS; ++i) - * { - * uip_tcppoll(dev,i); - * if (dev->d_len > 0) - * { - * devicedriver_send(); - * } - * } - * - * Note: If you are writing a uIP device driver that needs ARP - * (Address Resolution Protocol), e.g., when running uIP over - * Ethernet, you will need to call the uip_arp_out() function before - * calling the device driver: + * When the callback function is called, there may be an outbound packet + * waiting for service in the uIP packet buffer, and if so the d_len field + * is set to a value larger than zero. The device driver should be called to + * send out the packet. * - * for(i = 0; i < UIP_CONNS; ++i) + * Example: + * int driver_callback(struct uip_driver_dev *dev) + * { + * if (dev->d_len > 0) * { - * uip_tcppoll(dev,i); - * if (dev->d_len > 0) - * { - * uip_arp_out(); - * ethernet_devicedriver_send(); - * } + * devicedriver_send(); + * return 1; <-- Terminates polling if necessary * } + * return 0; + * } * - * conn The number of the connection which is to be periodically polled. - */ - -extern void uip_tcppoll(struct uip_driver_s *dev, unsigned int conn); - - #ifdef CONFIG_NET_UDP -/* Periodic processing for a UDP connection identified by its number. - * - * This function is essentially the same as uip_tcppoll(), but for - * UDP connections. It is called in a similar fashion as the - * uip_tcppoll() function: - * - * for(i = 0; i < UIP_UDP_CONNS; i++) - * { - * uip_udppoll(dev,i); - * if(dev->d_len > 0) - * { - * devicedriver_send(); - * } - * } + * ... + * uip_poll(dev, driver_callback, UIP_TIMER); * - * Note: As for the uip_tcppoll() function, special care has to be - * taken when using uIP together with ARP and Ethernet: + * Note: If you are writing a uIP device driver that needs ARP (Address + * Resolution Protocol), e.g., when running uIP over Ethernet, you will + * need to call the uip_arp_out() function in the callback function + * before sending the packet: * - * for(i = 0; i < UIP_UDP_CONNS; i++) + * int driver_callback(struct uip_driver_dev *dev) + * { + * if (dev->d_len > 0) * { - * uip_udppoll(dev,i); - * if(dev->d_len > 0) - * { - * uip_arp_out(); - * ethernet_devicedriver_send(); - * } + * uip_arp_out(); + * devicedriver_send(); + * return 1; <-- Terminates polling if necessary * } - * - * conn The number of the UDP connection to be processed. + * return 0; + * } */ -extern void uip_udppoll(struct uip_driver_s *dev, unsigned int conn); +typedef int (*uip_poll_callback_t)(struct uip_driver_s *dev); +extern int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback, int event); -#endif /* CONFIG_NET_UDP */ +/* uip_poll helper functions */ + +#define uip_periodic(dev,cb) uip_poll(dev,db,UIP_TIMER); /* Architecure support * @@ -326,7 +304,7 @@ extern void uip_udppoll(struct uip_driver_s *dev, unsigned int conn); * interrupt level by a device driver. */ -extern void uip_interrupt(struct uip_driver_s *dev, uint8 flag); +extern void uip_interrupt(struct uip_driver_s *dev, uint8 event); /* By defining UIP_ARCH_CHKSUM, the architecture can replace the following * functions with hardware assisted solutions. diff --git a/nuttx/include/net/uip/uip.h b/nuttx/include/net/uip/uip.h index 6853a2714..0b6465323 100644 --- a/nuttx/include/net/uip/uip.h +++ b/nuttx/include/net/uip/uip.h @@ -448,7 +448,7 @@ extern void *uip_urgdata; */ #if UIP_URGDATA > 0 -extern uint16 uip_urglen, uip_surglen; +extern uint16 uip_urglen; /* Length of (received) urgent data */ #endif /* UIP_URGDATA > 0 */ /* Pointer to the current TCP connection. @@ -598,7 +598,7 @@ int uip_unlisten(uint16 port); * * Note: This function does not guarantee that the sent data will * arrive at the destination. If the data is lost in the network, the - * application will be invoked with the uip_rexmit() event being + * application will be invoked with the uip_rexmit_event() event being * set. The application will then have to resend the data using this * function. * @@ -686,7 +686,7 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * avaliable through the d_len element. */ -#define uip_newdata() (uip_flags & UIP_NEWDATA) +#define uip_newdata_event() (uip_flags & UIP_NEWDATA) /* Has previously sent data been acknowledged? * @@ -695,17 +695,17 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * can send new data. */ -#define uip_acked() (uip_flags & UIP_ACKDATA) +#define uip_ack_event() (uip_flags & UIP_ACKDATA) /* Has the connection just been connected? * - * Reduces to non-zero if the current connection has been connected to + * Reduces to non-zero if the current connenetutils/telnetd/telnetd.cction has been connected to * a remote host. This will happen both if the connection has been * actively opened (with uip_connect()) or passively opened (with * uip_listen()). */ -#define uip_connected() (uip_flags & UIP_CONNECTED) +#define uip_connected_event() (uip_flags & UIP_CONNECTED) /* Has the connection been closed by the other end? * @@ -713,7 +713,7 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * host. The application may then do the necessary clean-ups. */ -#define uip_closed() (uip_flags & UIP_CLOSE) +#define uip_close_event() (uip_flags & UIP_CLOSE) /* Has the connection been aborted by the other end? * @@ -721,7 +721,7 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * remote host. */ -#define uip_aborted() (uip_flags & UIP_ABORT) +#define uip_abort_event() (uip_flags & UIP_ABORT) /* Has the connection timed out? * @@ -729,7 +729,7 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * retransmissions. */ -#define uip_timedout() (uip_flags & UIP_TIMEDOUT) +#define uip_timeout_event() (uip_flags & UIP_TIMEDOUT) /* Do we need to retransmit previously data? * @@ -739,7 +739,7 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * time, using the uip_send() function. */ -#define uip_rexmit() (uip_flags & UIP_REXMIT) +#define uip_rexmit_event() (uip_flags & UIP_REXMIT) /* Is the connection being polled by uIP? * @@ -751,7 +751,7 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * wait for the remote host to send data. */ -#define uip_poll() (uip_flags & UIP_POLL) +#define uip_poll_event() (uip_flags & UIP_POLL) /* Get the initial maxium segment size (MSS) of the current * connection. @@ -768,7 +768,7 @@ void uip_send(struct uip_driver_s *dev, const void *buf, int len); * uip_initialmss()). */ -#define uip_mss() (uip_conn->mss) +#define uip_mss() (uip_conn->mss) /* Bind a UDP connection to a local address */ diff --git a/nuttx/net/connect.c b/nuttx/net/connect.c index c520aaac8..7f3d17609 100644 --- a/nuttx/net/connect.c +++ b/nuttx/net/connect.c @@ -42,7 +42,10 @@ #include <sys/types.h> #include <sys/socket.h> + #include <errno.h> +#include <debug.h> + #include <arch/irq.h> #include "net-internal.h" @@ -186,6 +189,8 @@ static void tcp_connect_interrupt(struct uip_driver_s *dev, void *private) { struct tcp_connect_s *pstate = (struct tcp_connect_s *)private; + vdbg("Interrupt uip_flags=%02x\n", uip_flags); + /* 'private' might be null in some race conditions (?) */ if (pstate) @@ -209,6 +214,7 @@ static void tcp_connect_interrupt(struct uip_driver_s *dev, void *private) { /* Indicate that remote host refused the connection */ + vdbg("ECONNREFUSED\n"); pstate->tc_result = -ECONNREFUSED; } @@ -218,7 +224,8 @@ static void tcp_connect_interrupt(struct uip_driver_s *dev, void *private) { /* Indicate that the remote host is unreachable (or should this be timedout?) */ - pstate->tc_result = -ECONNREFUSED; + vdbg("ETIMEDOUT\n"); + pstate->tc_result = -ETIMEDOUT; } /* UIP_CONNECTED: The socket is successfully connected */ @@ -227,6 +234,7 @@ static void tcp_connect_interrupt(struct uip_driver_s *dev, void *private) { /* Indicate that the socket is no longer connected */ + vdbg("Connected\n"); pstate->tc_result = OK; } @@ -461,6 +469,8 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { case SOCK_STREAM: { + dbg("TCP\n"); + /* Verify that the socket is not already connected */ if (_SS_ISCONNECTED(psock->s_flags)) @@ -483,6 +493,8 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { + dbg("UDP\n"); + ret = uip_udpconnect(psock->s_conn, inaddr); if (ret < 0) { diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c index 25dc1c4fb..1ea76981f 100644 --- a/nuttx/net/recvfrom.c +++ b/nuttx/net/recvfrom.c @@ -42,8 +42,11 @@ #include <sys/types.h> #include <sys/socket.h> + #include <string.h> #include <errno.h> +#include <debug.h> + #include <arch/irq.h> #include <nuttx/clock.h> #include <net/uip/uip-arch.h> @@ -104,6 +107,8 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) #endif size_t recvlen; + vdbg("Interrupt uip_flags: %02x\n", uip_flags); + /* 'private' might be null in some race conditions (?) */ if (pstate) @@ -116,9 +121,10 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) /* If new data is available, then complete the read action. */ - if (uip_newdata()) + if (uip_newdata_event()) { /* Get the length of the data to return */ + if (dev->d_len > pstate->rf_buflen) { recvlen = pstate->rf_buflen; @@ -131,6 +137,7 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) /* Copy the new appdata into the user buffer */ memcpy(pstate->rf_buffer, dev->d_appdata, recvlen); + vdbg("Received %d bytes (of %d)\n", recvlen, dev->d_len); /* Update the accumulated size of the data read */ @@ -139,14 +146,16 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) pstate->rf_buflen -= recvlen; /* Are we finished? If this is a UDP socket or if the user - * buffer has been filled, then we are finished. - */ + * buffer has been filled, then we are finished. + */ #ifdef CONFIG_NET_UDP if (psock->s_type == SOCK_DGRAM) { struct uip_udp_conn *udp_conn; + vdbg("UDP complete\n"); + /* Don't allow any further UDP call backs. */ udp_conn = (struct uip_udp_conn *)psock->s_conn; @@ -165,6 +174,8 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) { struct uip_conn *conn; + vdbg("TCP complete\n"); + /* The TCP receive buffer is full. Return now, perhaps truncating * the received data (need to fix that). * @@ -183,8 +194,8 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) } /* Reset the timeout. We will want a short timeout to terminate - * the TCP receive. - */ + * the TCP receive. + */ #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) pstate->rf_starttime = g_system_timer; @@ -195,6 +206,8 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) else if ((uip_flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) { + vdbg("Receive error\n"); + /* Stop further callbacks */ #ifdef CONFIG_NET_UDP @@ -267,6 +280,8 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) { struct uip_udp_conn *udp_conn; + vdbg("UDP timeout\n"); + /* Stop further callbacks */ udp_conn = (struct uip_udp_conn *)psock->s_conn; @@ -282,6 +297,8 @@ static void recvfrom_interrupt(struct uip_driver_s *dev, void *private) { struct uip_conn *conn; + vdbg("TCP timeout\n"); + conn = (struct uip_conn *)psock->s_conn; conn->data_private = NULL; conn->data_event = NULL; @@ -463,7 +480,9 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, * and automatically re-enabled when the task restarts. */ + vdbg("Receiving UDP ...\n"); ret = sem_wait(&state. rf_sem); + vdbg("Received\n"); /* Make sure that no further interrupts are processed */ @@ -540,7 +559,9 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, * and automatically re-enabled when the task restarts. */ + vdbg("Receiving UDP ...\n"); ret = sem_wait(&state.rf_sem); + vdbg("Received\n"); /* Make sure that no further interrupts are processed */ diff --git a/nuttx/net/send.c b/nuttx/net/send.c index dc5dbc75b..07a3a0a72 100644 --- a/nuttx/net/send.c +++ b/nuttx/net/send.c @@ -42,8 +42,11 @@ #include <sys/types.h> #include <sys/socket.h> + #include <string.h> #include <errno.h> +#include <debug.h> + #include <arch/irq.h> #include "net-internal.h" @@ -101,11 +104,13 @@ static void send_interrupt(struct uip_driver_s *dev, void *private) struct send_s *pstate = (struct send_s *)private; struct uip_conn *conn; + vdbg("Interrupt uip_flags: %02x state: %d\n", uip_flags, pstate->snd_state); + /* If the data has not been sent OR if it needs to be retransmitted, * then send it now. */ - if (pstate->snd_state != STATE_DATA_SENT || uip_rexmit()) + if (pstate->snd_state != STATE_DATA_SENT || uip_rexmit_event()) { if (pstate->snd_buflen > uip_mss()) { @@ -117,11 +122,12 @@ static void send_interrupt(struct uip_driver_s *dev, void *private) } pstate->snd_state = STATE_DATA_SENT; + vdbg("state: STATE_DATA_SENT(%d)\n", STATE_DATA_SENT); } /* Check if all data has been sent and acknowledged */ - else if (pstate->snd_state == STATE_DATA_SENT && uip_acked()) + else if (pstate->snd_state == STATE_DATA_SENT && uip_ack_event()) { /* Yes.. the data has been sent AND acknowledge */ @@ -136,9 +142,12 @@ static void send_interrupt(struct uip_driver_s *dev, void *private) /* Send again on the next poll */ pstate->snd_state = STATE_POLLWAIT; + vdbg("state: STATE_POLLWAIT(%d)\n", STATE_POLLWAIT); } else { + vdbg("state: Data sent\n"); + /* All data has been sent */ pstate->snd_sent += pstate->snd_buflen; @@ -163,6 +172,8 @@ static void send_interrupt(struct uip_driver_s *dev, void *private) else if ((uip_flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) { + vdbg("state: TCP failure\n"); + /* Stop further callbacks */ conn = (struct uip_conn *)pstate->snd_sock->s_conn; @@ -305,12 +316,14 @@ ssize_t send(int sockfd, const void *buf, size_t len, int flags) * automatically re-enabled when the task restarts. */ + vdbg("Sending %d bytes...\n", len); ret = sem_wait(&state. snd_sem); /* Make sure that no further interrupts are processed */ conn->data_private = NULL; conn->data_event = NULL; + vdbg("Sent\n"); } sem_destroy(&state. snd_sem); diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs index 61f89cc7b..c76f76299 100644 --- a/nuttx/net/uip/Make.defs +++ b/nuttx/net/uip/Make.defs @@ -35,5 +35,5 @@ UIP_ASRCS = UIP_CSRCS = uip-arp.c uip.c uip-send.c uip-fw.c uip-neighbor.c uip-split.c \ - uip-tcpconn.c uip-udpconn.c uip-listen.c + uip-tcpconn.c uip-udpconn.c uip-listen.c uip-poll.c diff --git a/nuttx/net/uip/uip-arp.c b/nuttx/net/uip/uip-arp.c index 9a82943fa..fa64f9876 100644 --- a/nuttx/net/uip/uip-arp.c +++ b/nuttx/net/uip/uip-arp.c @@ -52,6 +52,9 @@ * Included Files ****************************************************************************/ +#include <nuttx/config.h> +#ifdef CONFIG_NET + #include <sys/types.h> #include <sys/ioctl.h> @@ -144,13 +147,13 @@ static void uip_arp_dump(struct arp_hdr *arp) vdbg(" Sender MAC: %02x:%02x:%02x:%02x:%02x:%02x IP: %d.%d.%d.%d\n", arp->ah_shwaddr[0], arp->ah_shwaddr[1], arp->ah_shwaddr[2], arp->ah_shwaddr[3], arp->ah_shwaddr[4], arp->ah_shwaddr[5], - arp->ah_sipaddr[0] >> 8, arp->ah_sipaddr[0] & 0xff, - arp->ah_sipaddr[1] >> 8, arp->ah_sipaddr[1] & 0xff); + arp->ah_sipaddr[0] & 0xff, arp->ah_sipaddr[0] >> 8, + arp->ah_sipaddr[1] & 0xff, arp->ah_sipaddr[1] >> 8); vdbg(" Dest MAC: %02x:%02x:%02x:%02x:%02x:%02x IP: %d.%d.%d.%d\n", arp->ah_dhwaddr[0], arp->ah_dhwaddr[1], arp->ah_dhwaddr[2], arp->ah_dhwaddr[3], arp->ah_dhwaddr[4], arp->ah_dhwaddr[5], - arp->ah_dipaddr[0] >> 8, arp->ah_dipaddr[0] & 0xff, - arp->ah_dipaddr[1] >> 8, arp->ah_dipaddr[1] & 0xff); + arp->ah_dipaddr[0] & 0xff, arp->ah_dipaddr[0] >> 8, + arp->ah_dipaddr[1] & 0xff, arp->ah_dipaddr[1] >> 8); } #else # define uip_arp_dump(arp) @@ -324,6 +327,7 @@ void uip_arp_ipin(void) void uip_arp_arpin(struct uip_driver_s *dev) { in_addr_t ipaddr; + if (dev->d_len < (sizeof(struct arp_hdr) + UIP_LLH_LEN)) { dev->d_len = 0; @@ -357,8 +361,7 @@ void uip_arp_arpin(struct uip_driver_s *dev) ARPBUF->ah_dipaddr[0] = ARPBUF->ah_sipaddr[0]; ARPBUF->ah_dipaddr[1] = ARPBUF->ah_sipaddr[1]; - ARPBUF->ah_sipaddr[0] = dev->d_ipaddr >> 16; - ARPBUF->ah_sipaddr[1] = dev->d_ipaddr & 0xffff; + uiphdr_ipaddr_copy(ARPBUF->ah_sipaddr, &dev->d_ipaddr); uip_arp_dump(ARPBUF); ETHBUF->type = HTONS(UIP_ETHTYPE_ARP); @@ -503,3 +506,4 @@ void uip_arp_out(struct uip_driver_s *dev) ETHBUF->type = HTONS(UIP_ETHTYPE_IP); dev->d_len += UIP_LLH_LEN; } +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip-internal.h b/nuttx/net/uip/uip-internal.h index 6c76f39cf..9b293abef 100644 --- a/nuttx/net/uip/uip-internal.h +++ b/nuttx/net/uip/uip-internal.h @@ -78,6 +78,7 @@ extern "C" { EXTERN void uip_tcpinit(void); EXTERN struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf); +EXTERN struct uip_conn *uip_nexttcpconn(struct uip_conn *conn); EXTERN struct uip_conn *uip_tcplistener(uint16 portno); EXTERN struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf); EXTERN void uip_tcpnextsequence(void); @@ -86,6 +87,7 @@ EXTERN void uip_tcpnextsequence(void); EXTERN void uip_udpinit(void); EXTERN struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf); +EXTERN struct uip_udp_conn *uip_nextudpconn(struct uip_udp_conn *conn); /* Defined in uip_listen.c **************************************************/ diff --git a/nuttx/net/uip/uip-poll.c b/nuttx/net/uip/uip-poll.c new file mode 100644 index 000000000..e6470dfe7 --- /dev/null +++ b/nuttx/net/uip/uip-poll.c @@ -0,0 +1,161 @@ +/**************************************************************************** + * net/uip/uip-poll.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 <nuttx/config.h> +#ifdef CONFIG_NET + +#include <sys/types.h> +#include <debug.h> + +#include <net/uip/uipopt.h> +#include <net/uip/uip.h> +#include <net/uip/uip-arch.h> + +#include "uip-internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_udppoll() + * + * Description: + * Periodic processing for a UDP 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. + * + ****************************************************************************/ + +static inline void uip_udppoll(struct uip_driver_s *dev, unsigned int conn) +{ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip-poll + * + * Description: + * This function will traverse each active uIP connection structure and + * perform uip_interrupt with the specified event. After each polling each + * active uIP connection structure, this function will call the provided + * callback function if the poll resulted in new data to be send. The poll + * will continue until all connections have been polled or until the user- + * suplied function returns a non-zero value (which is would do only if + * it cannot accept further write data). + * + * This function should be called periodically with event == UIP_TIMER for + * periodic processing. This function may also be called with UIP_POLL to + * perform necessary periodic processing of TCP connections. + * + * When the callback function is called, there may be an outbound packet + * waiting for service in the uIP packet buffer, and if so the d_len field + * is set to a value larger than zero. The device driver should be called to + * send out the packet. + * + * Assumptions: + * This function is called from the CAN device driver and may be called from + * the timer interrupt/watchdog handle level. + * + ****************************************************************************/ + +int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback, int event) +{ + struct uip_conn *conn; +#ifdef CONFIG_NET_UDP + struct uip_udp_conn *udp_conn; +#endif + irqstate_t flags; + + /* Interrupts must be disabled while traversing the active connection list */ + + flags = irqsave(); + + /* Traverse all of the active TCP connections and perform the poll action */ + + conn = NULL; + while ((conn = uip_nexttcpconn(uip_conn))) + { + uip_conn = conn; + uip_interrupt(dev, event); + if (callback(dev)) + { + irqrestore(flags); + return 1; + } + } + uip_conn = NULL; + +#ifdef CONFIG_NET_UDP + /* Traverse all of the allocated UDP connections and perform a poll action */ + + udp_conn = NULL; + while ((udp_conn = uip_nextudpconn(uip_udp_conn))) + { + uip_udp_conn = udp_conn; + uip_interrupt(dev, UIP_UDP_POLL); + if (callback(dev)) + { + irqrestore(flags); + return 1; + } + } + uip_udp_conn = NULL; +#endif /* CONFIG_NET_UDP */ + + irqrestore(flags); + return 0; +} + +#endif /* CONFIG_NET */ diff --git a/nuttx/net/uip/uip-tcpconn.c b/nuttx/net/uip/uip-tcpconn.c index b8bcdb3ce..2a341019e 100644 --- a/nuttx/net/uip/uip-tcpconn.c +++ b/nuttx/net/uip/uip-tcpconn.c @@ -50,6 +50,8 @@ #include <sys/types.h> #include <string.h> #include <errno.h> +#include <debug.h> + #include <arch/irq.h> #include <net/uip/uipopt.h> @@ -316,14 +318,26 @@ void uip_tcpfree(struct uip_conn *conn) struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf) { - struct uip_conn *conn = (struct uip_conn *)g_active_tcp_connections.head; + struct uip_conn *conn = (struct uip_conn *)g_active_tcp_connections.head; + in_addr_t srcipaddr = uip_ip4addr_conv(buf->srcipaddr); + + vdbg("BUF: destport: %04x srcport: %04x IP: %d.%d.%d.%d\n", + buf->destport, buf->srcport, + (srcipaddr >> 24) & 0xff, (srcipaddr >> 16) & 0xff, + (srcipaddr >> 8) & 0xff, srcipaddr & 0xff); + while (conn) { /* Find an open connection matching the tcp input */ + vdbg("conn: lport: %04x rport: %04x IP: %d.%d.%d.%d\n", + conn->lport, conn->rport, + (conn->ripaddr >> 24) & 0xff, (conn->ripaddr >> 16) & 0xff, + (conn->ripaddr >> 8) & 0xff, conn->ripaddr & 0xff); + if (conn->tcpstateflags != UIP_CLOSED && - buf->destport == conn->lport && buf->srcport == conn->rport && - uip_ipaddr_cmp(buf->srcipaddr, conn->ripaddr)) + buf->destport == conn->lport && buf->srcport == conn->rport && + uip_ipaddr_cmp(srcipaddr, conn->ripaddr)) { /* Matching connection found.. break out of the loop and return a * reference to it. @@ -341,6 +355,30 @@ struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf) } /**************************************************************************** + * Name: uip_nexttcpconn() + * + * Description: + * Traverse the list of active TCP connections + * + * Assumptions: + * This function is called from UIP logic at interrupt level (or with + * interrupts disabled). + * + ****************************************************************************/ + +struct uip_conn *uip_nexttcpconn(struct uip_conn *conn) +{ + if (!conn) + { + return (struct uip_conn *)g_active_tcp_connections.head; + } + else + { + return (struct uip_conn *)conn->node.flink; + } +} + +/**************************************************************************** * Name: uip_tcplistener() * * Description: @@ -418,29 +456,6 @@ struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf) } /**************************************************************************** - * Name: uip_tcppoll() - * - * Description: - * Periodic processing for a TCP 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(struct uip_driver_s *dev, unsigned int conn) -{ - uip_conn = &g_tcp_connections[conn]; - uip_interrupt(dev, UIP_TIMER); -} - -/**************************************************************************** * Name: uip_tcpnextsequence() * * Description: diff --git a/nuttx/net/uip/uip-udpconn.c b/nuttx/net/uip/uip-udpconn.c index e1cb17418..f5779453a 100644 --- a/nuttx/net/uip/uip-udpconn.c +++ b/nuttx/net/uip/uip-udpconn.c @@ -249,7 +249,7 @@ struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf) (conn->rport == 0 || buf->srcport == conn->rport) && (uip_ipaddr_cmp(conn->ripaddr, all_zeroes_addr) || uip_ipaddr_cmp(conn->ripaddr, all_ones_addr) || - uip_ipaddr_cmp(buf->srcipaddr, conn->ripaddr))) + uiphdr_ipaddr_cmp(buf->srcipaddr, conn->ripaddr))) { /* Matching connection found.. return a reference to it */ @@ -265,26 +265,27 @@ struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf) } /**************************************************************************** - * Name: uip_udppoll() + * Name: uip_nextudpconn() * * Description: - * Periodic processing for a UDP 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. + * Traverse the list of allocated UDP connections * * Assumptions: - * This function is called from the CAN device driver may be called from - * the timer interrupt/watchdog handle level. + * This function is called from UIP logic at interrupt level (or with + * interrupts disabled). * ****************************************************************************/ -void uip_udppoll(struct uip_driver_s *dev, unsigned int conn) +struct uip_udp_conn *uip_nextudpconn(struct uip_udp_conn *conn) { - uip_udp_conn = &g_udp_connections[conn]; - uip_interrupt(dev, UIP_UDP_TIMER); + if (!conn) + { + return (struct uip_udp_conn *)g_active_udp_connections.head; + } + else + { + return (struct uip_udp_conn *)conn->node.flink; + } } /**************************************************************************** @@ -320,11 +321,11 @@ int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr) * Name: uip_udpconnect() * * Description: - * 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_udpbind() call, after the uip_udpconnect() function has been - * called. + * 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_udpbind() call, after the uip_udpconnect() function has been + * called. * * uip_udpenable() must be called before the connection is made active (i.e., * is eligible for callbacks. diff --git a/nuttx/net/uip/uip.c b/nuttx/net/uip/uip.c index 279140067..cc5c93e8a 100644 --- a/nuttx/net/uip/uip.c +++ b/nuttx/net/uip/uip.c @@ -11,7 +11,7 @@ * code size is on the order of a few kilobytes and RAM usage is on * the order of a few hundred bytes. * - * Copyright (c) 2001-2003, Adam Dunkels. + * Copyright () 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,9 +73,13 @@ ****************************************************************************/ #include <nuttx/config.h> +#ifdef CONFIG_NET + #include <sys/types.h> #include <sys/ioctl.h> + #include <debug.h> +#include <string.h> #include <net/uip/uipopt.h> #include <net/uip/uip.h> @@ -85,8 +89,6 @@ # include "uip-neighbor.h" #endif /* CONFIG_NET_IPv6 */ -#include <string.h> - /* Check if logging of network events should be compiled in. * * This is useful mostly for debugging. The function uip_log() @@ -147,11 +149,9 @@ extern void uip_log(char *msg); ****************************************************************************/ #if UIP_URGDATA > 0 -void *uip_urgdata; /* The uip_urgdata pointer points to urgent data - * (out-of-band data), if present. */ -uint16 uip_urglen; -uint16 uip_surglen; -#endif /* UIP_URGDATA > 0 */ +void *uip_urgdata; /* urgent data (out-of-band data), if present. */ +uint16 uip_urglen; /* Length of (received) urgent data */ +#endif /* The uip_flags variable is used for communication between the TCP/IP * stack and the application program. @@ -196,14 +196,7 @@ const uip_ipaddr_t all_zeroes_addr = * Private Variables ****************************************************************************/ -static uint16 ipid; /* Ths ipid variable is an increasing number that is - * used for the IP ID field. */ - -/* Temporary variables. */ - -static uint8 c; -static uint8 opt; -static uint16 tmp16; +static uint16 g_ipid; /* Increasing number used for the IP ID field. */ /**************************************************************************** * Private Functions @@ -289,7 +282,7 @@ static uint16 uip_icmp6chksum(struct uip_driver_s *dev) void uip_setipid(uint16 id) { - ipid = id; + g_ipid = id; } /* Calculate the Internet checksum over a buffer. */ @@ -340,7 +333,7 @@ uint16 uip_ipchksum(struct uip_driver_s *dev) uint16 sum; sum = chksum(0, &dev->d_buf[UIP_LLH_LEN], UIP_IPH_LEN); - dbg("Checksum 0x%04x\n", sum); + vdbg("Checksum 0x%04x\n", sum); return (sum == 0) ? 0xffff : htons(sum); } #endif @@ -365,7 +358,7 @@ uint16 uip_udpchksum(struct uip_driver_s *dev) void uip_init(void) { /* Initialize the listening port structures */ - + uip_listeninit(); /* Initialize the TCP/IP connection structures */ @@ -422,7 +415,7 @@ static uint8 uip_reass(void) if (uiphdr_addr_cmp(BUF->srcipaddr, FBUF->srcipaddr) && uiphdr_addr_cmp(BUF->destipaddr == FBUF->destipaddr) && - BUF->ipid[0] == FBUF->ipid[0] && BUF->ipid[1] == FBUF->ipid[1]) + BUF->g_ipid[0] == FBUF->g_ipid[0] && BUF->g_ipid[1] == FBUF->g_ipid[1]) { len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; @@ -544,6 +537,8 @@ static void uip_add_rcv_nxt(uint16 n) #ifdef CONFIG_NET_UDP static void uip_udp_callback(struct uip_driver_s *dev) { + vdbg("UDP callback uip_flags: %02x\n", uip_flags); + /* Some sanity checking */ if (uip_udp_conn && uip_udp_conn->event) @@ -557,6 +552,8 @@ static void uip_udp_callback(struct uip_driver_s *dev) static void uip_tcp_callback(struct uip_driver_s *dev) { + vdbg("TCP callback uip_flags: %02x\n", uip_flags); + /* Some sanity checking */ if (uip_conn) @@ -582,16 +579,14 @@ static void uip_tcp_callback(struct uip_driver_s *dev) } } -void uip_interrupt(struct uip_driver_s *dev, uint8 flag) +void uip_interrupt(struct uip_driver_s *dev, uint8 event) { register struct uip_conn *uip_connr = uip_conn; - -#ifdef CONFIG_NET_UDP - if (flag == UIP_UDP_SEND_CONN) - { - goto udp_send; - } -#endif /* CONFIG_NET_UDP */ + uint16 tmp16; + uint8 seqbyte; + uint8 opt; + int len; + int i; dev->d_snddata = dev->d_appdata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; @@ -599,8 +594,9 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) * particular connection. */ - if (flag == UIP_POLL_REQUEST) + if (event == UIP_POLL_REQUEST) { + vdbg("event: UIP_POLL_REQUEST\n"); if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && !uip_outstanding(uip_connr)) { @@ -613,7 +609,7 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) /* Check if we were invoked because of the perodic timer firing. */ - else if (flag == UIP_TIMER) + else if (event == UIP_TIMER) { #if UIP_REASSEMBLY if (uip_reasstmr != 0) @@ -644,6 +640,7 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) if (uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { uip_connr->tcpstateflags = UIP_CLOSED; + vdbg("TCP state: UIP_CLOSED\n"); } } else if (uip_connr->tcpstateflags != UIP_CLOSED) @@ -663,6 +660,7 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) uip_connr->nrtx == UIP_MAXSYNRTX)) { uip_connr->tcpstateflags = UIP_CLOSED; + vdbg("TCP state: UIP_CLOSED\n"); /* We call uip_tcp_callback() with uip_flags set to * UIP_TIMEDOUT to inform the application that the @@ -684,7 +682,7 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) ++(uip_connr->nrtx); /* Ok, so we need to retransmit. We do this differently - * depending on which state we are in. In ESTABLISHED, we + * depending on which state we are in. In ESTABLISHED, we * call upon the application so that it may prepare the * data for the retransmit. In SYN_RCVD, we resend the * SYNACK that we sent earlier and in LAST_ACK we have to @@ -703,6 +701,7 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) case UIP_SYN_SENT: /* In the SYN_SENT state, we retransmit out SYN. */ + BUF->flags = 0; goto tcp_send_syn; @@ -721,8 +720,8 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) case UIP_CLOSING: case UIP_LAST_ACK: /* In all these states we should retransmit a FINACK. */ - goto tcp_send_finack; + goto tcp_send_finack; } } } @@ -737,19 +736,19 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) goto appsend; } } - goto drop; - } + goto drop; + } #ifdef CONFIG_NET_UDP - if (flag == UIP_UDP_TIMER) + else if (event == UIP_POLL) { if (uip_udp_conn->lport != 0) { - uip_conn = NULL; + uip_conn = NULL; dev->d_snddata = dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; - dev->d_len = 0; - dev->d_sndlen = 0; - uip_flags = UIP_POLL; + dev->d_len = 0; + dev->d_sndlen = 0; + uip_flags = UIP_POLL; uip_udp_callback(dev); goto udp_send; } @@ -761,1162 +760,1335 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) #endif /* This is where the input processing starts. */ + + vdbg("event: %d\n", event); UIP_STAT(++uip_stat.ip.recv); /* Start of IP input header processing code. */ #ifdef CONFIG_NET_IPv6 /* Check validity of the IP header. */ + if ((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.vhlerr); UIP_LOG("ipv6: invalid version."); goto drop; } #else /* CONFIG_NET_IPv6 */ - /* Check validity of the IP header. */ - if (BUF->vhl != 0x45) - { - /* IP version and header length. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.vhlerr); - UIP_LOG("ip: invalid version or header length."); - goto drop; - } + /* Check validity of the IP header. */ + + if (BUF->vhl != 0x45) + { + /* IP version and header length. */ + + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ip: invalid version or header length."); + goto drop; + } #endif /* CONFIG_NET_IPv6 */ - /* Check the size of the packet. If the size reported to us in - d_len is smaller the size reported in the IP header, we assume - that the packet has been corrupted in transit. If the size of - d_len is larger than the size reported in the IP packet header, - the packet has been padded and we set d_len to the correct - value.. */ + /* Check the size of the packet. If the size reported to us in d_len is + * smaller the size reported in the IP header, we assume that the packet + * has been corrupted in transit. If the size of d_len is larger than the + * size reported in the IP packet header, the packet has been padded and + * we set d_len to the correct value. + */ - if ((BUF->len[0] << 8) + BUF->len[1] <= dev->d_len) - { - dev->d_len = (BUF->len[0] << 8) + BUF->len[1]; + if ((BUF->len[0] << 8) + BUF->len[1] <= dev->d_len) + { + dev->d_len = (BUF->len[0] << 8) + BUF->len[1]; #ifdef CONFIG_NET_IPv6 - dev->d_len += 40; /* The length reported in the IPv6 header is the - length of the payload that follows the - header. However, uIP uses the d_len variable - for holding the size of the entire packet, - including the IP header. For IPv4 this is not a - problem as the length field in the IPv4 header - contains the length of the entire packet. But - for IPv6 we need to add the size of the IPv6 - header (40 bytes). */ + /* The length reported in the IPv6 header is the length of the + * payload that follows the header. However, uIP uses the d_len + * variable for holding the size of the entire packet, including the + * IP header. For IPv4 this is not a problem as the length field in + * the IPv4 header contains the length of the entire packet. But + * for IPv6 we need to add the size of the IPv6 header (40 bytes). + */ + + dev->d_len += 40; #endif /* CONFIG_NET_IPv6 */ - } - else - { - UIP_LOG("ip: packet shorter than reported in IP header."); - goto drop; - } + } + else + { + UIP_LOG("ip: packet shorter than reported in IP header."); + goto drop; + } #ifndef CONFIG_NET_IPv6 - /* Check the fragment flag. */ + /* Check the fragment flag. */ - if ((BUF->ipoffset[0] & 0x3f) != 0 || - BUF->ipoffset[1] != 0) - { + if ((BUF->ipoffset[0] & 0x3f) != 0 || BUF->ipoffset[1] != 0) + { #if UIP_REASSEMBLY - dev->d_len = uip_reass(); - if (dev->d_len == 0) - { - goto drop; - } + dev->d_len = uip_reass(); + if (dev->d_len == 0) + { + goto drop; + } #else /* UIP_REASSEMBLY */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.fragerr); - UIP_LOG("ip: fragment dropped."); - goto drop; + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.fragerr); + UIP_LOG("ip: fragment dropped."); + goto drop; #endif /* UIP_REASSEMBLY */ - } + } #endif /* CONFIG_NET_IPv6 */ - if (uip_ipaddr_cmp(dev->d_ipaddr, all_zeroes_addr)) - { - /* If we are configured to use ping IP address configuration and - hasn't been assigned an IP address yet, we accept all ICMP - packets. */ + if (uip_ipaddr_cmp(dev->d_ipaddr, all_zeroes_addr)) + { + /* If we are configured to use ping IP address configuration and + * hasn't been assigned an IP address yet, we accept all ICMP + * packets. + */ + #if UIP_PINGADDRCONF && !CONFIG_NET_IPv6 - if (BUF->proto == UIP_PROTO_ICMP) - { - UIP_LOG("ip: possible ping config packet received."); - goto icmp_input; - } - else - { - UIP_LOG("ip: packet dropped since no address assigned."); - goto drop; - } + if (BUF->proto == UIP_PROTO_ICMP) + { + UIP_LOG("ip: possible ping config packet received."); + goto icmp_input; + } + else + { + UIP_LOG("ip: packet dropped since no address assigned."); + goto drop; + } #endif /* UIP_PINGADDRCONF */ + } + else + { + /* If IP broadcast support is configured, we check for a broadcast + * UDP packet, which may be destined to us. + */ - } - else - { - /* If IP broadcast support is configured, we check for a broadcast - UDP packet, which may be destined to us. */ #if UIP_BROADCAST - dbg("UDP IP checksum 0x%04x\n", uip_ipchksum(dev)); - if (BUF->proto == UIP_PROTO_UDP && - uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) - /*&& uip_ipchksum(dev) == 0xffff*/) - { - goto udp_input; - } + vdbg("UDP IP checksum 0x%04x\n", uip_ipchksum(dev)); + if (BUF->proto == UIP_PROTO_UDP && + uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) + /*&& uip_ipchksum(dev) == 0xffff*/) + { + goto udp_input; + } #endif /* UIP_BROADCAST */ - /* Check if the packet is destined for our IP address. */ + /* Check if the packet is destined for our IP address. */ #ifndef CONFIG_NET_IPv6 - if (!uip_ipaddr_cmp(uip_ip4addr_conv(BUF->destipaddr), dev->d_ipaddr)) - { - UIP_STAT(++uip_stat.ip.drop); - goto drop; - } + if (!uip_ipaddr_cmp(uip_ip4addr_conv(BUF->destipaddr), dev->d_ipaddr)) + { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } #else /* CONFIG_NET_IPv6 */ - /* For IPv6, packet reception is a little trickier as we need to - * make sure that we listen to certain multicast addresses (all - * hosts multicast address, and the solicited-node multicast - * address) as well. However, we will cheat here and accept all - * multicast packets that are sent to the ff02::/16 addresses. - */ + /* For IPv6, packet reception is a little trickier as we need to + * make sure that we listen to certain multicast addresses (all + * hosts multicast address, and the solicited-node multicast + * address) as well. However, we will cheat here and accept all + * multicast packets that are sent to the ff02::/16 addresses. + */ - if (!uip_ipaddr_cmp(BUF->destipaddr, dev->d_ipaddr) && - BUF->destipaddr & HTONL(0xffff0000) != HTONL(0xff020000)) - { - UIP_STAT(++uip_stat.ip.drop); - goto drop; - } + if (!uip_ipaddr_cmp(BUF->destipaddr, dev->d_ipaddr) && + BUF->destipaddr & HTONL(0xffff0000) != HTONL(0xff020000)) + { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } #endif /* CONFIG_NET_IPv6 */ - } + } #ifndef CONFIG_NET_IPv6 - if (uip_ipchksum(dev) != 0xffff) - { - /* Compute and check the IP header checksum. */ + if (uip_ipchksum(dev) != 0xffff) + { + /* Compute and check the IP header checksum. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.chkerr); - UIP_LOG("ip: bad checksum."); - goto drop; - } + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.chkerr); + UIP_LOG("ip: bad checksum."); + goto drop; + } #endif /* CONFIG_NET_IPv6 */ - if (BUF->proto == UIP_PROTO_TCP) - { - /* Check for TCP packet. If so, proceed with TCP input processing. */ + if (BUF->proto == UIP_PROTO_TCP) + { + /* Check for TCP packet. If so, proceed with TCP input processing. */ - goto tcp_input; - } + goto tcp_input; + } #ifdef CONFIG_NET_UDP - if (BUF->proto == UIP_PROTO_UDP) - { - goto udp_input; - } + if (BUF->proto == UIP_PROTO_UDP) + { + goto udp_input; + } #endif /* CONFIG_NET_UDP */ #ifndef CONFIG_NET_IPv6 - /* ICMPv4 processing code follows. */ - if (BUF->proto != UIP_PROTO_ICMP) - { - /* We only allow ICMP packets from here. */ + /* ICMPv4 processing code follows. */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.protoerr); - UIP_LOG("ip: neither tcp nor icmp."); - goto drop; - } + if (BUF->proto != UIP_PROTO_ICMP) + { + /* We only allow ICMP packets from here. */ + + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp."); + goto drop; + } #if UIP_PINGADDRCONF - icmp_input: +icmp_input: + vdbg("icmp_input\n"); #endif /* UIP_PINGADDRCONF */ - UIP_STAT(++uip_stat.icmp.recv); + UIP_STAT(++uip_stat.icmp.recv); - /* ICMP echo (i.e., ping) processing. This is simple, we only change - the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP - checksum before we return the packet. */ - if (ICMPBUF->type != ICMP_ECHO) - { - UIP_STAT(++uip_stat.icmp.drop); - UIP_STAT(++uip_stat.icmp.typeerr); - UIP_LOG("icmp: not icmp echo."); - goto drop; - } + /* ICMP echo (i.e., ping) processing. This is simple, we only change + * the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP + * checksum before we return the packet. + */ + + if (ICMPBUF->type != ICMP_ECHO) + { + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: not icmp echo."); + goto drop; + } + + /* If we are configured to use ping IP address assignment, we use + * the destination IP address of this ping packet and assign it to + * ourself. + */ - /* If we are configured to use ping IP address assignment, we use - the destination IP address of this ping packet and assign it to - ourself. */ #if UIP_PINGADDRCONF - if (dev->d_ipaddr == 0) - { - dev->d_ipaddr = BUF->destipaddr; - } + if (dev->d_ipaddr == 0) + { + dev->d_ipaddr = BUF->destipaddr; + } #endif /* UIP_PINGADDRCONF */ - ICMPBUF->type = ICMP_ECHO_REPLY; + ICMPBUF->type = ICMP_ECHO_REPLY; - if (ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) - { - ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; - } - else - { - ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); - } - - /* Swap IP addresses. */ + if (ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) + { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; + } + else + { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); + } - uiphdr_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); - uiphdr_ipaddr_copy(BUF->srcipaddr, &dev->d_ipaddr); + /* Swap IP addresses. */ - UIP_STAT(++uip_stat.icmp.sent); - goto send; + uiphdr_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uiphdr_ipaddr_copy(BUF->srcipaddr, &dev->d_ipaddr); - /* End of IPv4 input header processing code. */ + UIP_STAT(++uip_stat.icmp.sent); + goto send; #else /* !CONFIG_NET_IPv6 */ - /* This is IPv6 ICMPv6 processing code. */ - dbg("ICMP6 input length %d\n", dev->d_len); + /* This is IPv6 ICMPv6 processing code. */ - if (BUF->proto != UIP_PROTO_ICMP6) - { - /* We only allow ICMPv6 packets from here. */ + vdbg("ICMP6 input length %d\n", dev->d_len); - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.protoerr); - UIP_LOG("ip: neither tcp nor icmp6."); - goto drop; - } + if (BUF->proto != UIP_PROTO_ICMP6) + { + /* We only allow ICMPv6 packets from here. */ - UIP_STAT(++uip_stat.icmp.recv); + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp6."); + goto drop; + } - /* If we get a neighbor solicitation for our address we should send - a neighbor advertisement message back. */ - if (ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) - { - if (uip_ipaddr_cmp(ICMPBUF->icmp6data, dev->d_ipaddr)) - { - if (ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) - { - /* Save the sender's address in our neighbor list. */ - uiphdr_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); - } + UIP_STAT(++uip_stat.icmp.recv); - /* We should now send a neighbor advertisement back to where the - neighbor solicication came from. */ - ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; - ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ - - ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; - - uiphdr_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr); - uiphdr_ipaddr_copy(ICMPBUF->srcipaddr, dev->d_ipaddr); - ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; - ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ - memcpy(&(ICMPBUF->options[2]), &dev->d_mac, IFHWADDRLEN); - ICMPBUF->icmpchksum = 0; - ICMPBUF->icmpchksum = ~uip_icmp6chksum(dev); - goto send; - } - goto drop; - } - else if (ICMPBUF->type == ICMP6_ECHO) - { - /* ICMP echo (i.e., ping) processing. This is simple, we only - change the ICMP type from ECHO to ECHO_REPLY and update the - ICMP checksum before we return the packet. */ + /* If we get a neighbor solicitation for our address we should send + * a neighbor advertisement message back. + */ - ICMPBUF->type = ICMP6_ECHO_REPLY; + if (ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) + { + if (uip_ipaddr_cmp(ICMPBUF->icmp6data, dev->d_ipaddr)) + { + if (ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) + { + /* Save the sender's address in our neighbor list. */ - uiphdr_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); - uiphdr_ipaddr_copy(BUF->srcipaddr, dev->d_ipaddr); - ICMPBUF->icmpchksum = 0; - ICMPBUF->icmpchksum = ~uip_icmp6chksum(dev); + uiphdr_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); + } - UIP_STAT(++uip_stat.icmp.sent); - goto send; - } - else - { - dbg("Unknown ICMP6 message: %d\n", ICMPBUF->type); - UIP_STAT(++uip_stat.icmp.drop); - UIP_STAT(++uip_stat.icmp.typeerr); - UIP_LOG("icmp: unknown ICMP message."); - goto drop; - } + /* We should now send a neighbor advertisement back to where the + * neighbor solicication came from. + */ + + ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; + ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ - /* End of IPv6 ICMP processing. */ + ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; + uiphdr_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr); + uiphdr_ipaddr_copy(ICMPBUF->srcipaddr, dev->d_ipaddr); + ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; + ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ + memcpy(&(ICMPBUF->options[2]), &dev->d_mac, IFHWADDRLEN); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(dev); + goto send; + } + goto drop; + } + else if (ICMPBUF->type == ICMP6_ECHO) + { + /* ICMP echo (i.e., ping) processing. This is simple, we only + * change the ICMP type from ECHO to ECHO_REPLY and update the + * ICMP checksum before we return the packet. + */ + + ICMPBUF->type = ICMP6_ECHO_REPLY; + + uiphdr_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uiphdr_ipaddr_copy(BUF->srcipaddr, dev->d_ipaddr); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(dev); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + } + else + { + vdbg("Unknown ICMP6 message: %d\n", ICMPBUF->type); + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: unknown ICMP message."); + goto drop; + } #endif /* !CONFIG_NET_IPv6 */ #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 d_sndlen, it has a packet to - send. */ + /* UDP input processing. */ + +udp_input: + vdbg("udp_input\n"); + + /* 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 d_sndlen, it has a packet to + * send. + */ + #ifdef CONFIG_NET_UDP_CHECKSUMS - dev->d_len -= UIP_IPUDPH_LEN; - dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; - if (UDPBUF->udpchksum != 0 && uip_udpchksum(dev) != 0xffff) - { - UIP_STAT(++uip_stat.udp.drop); - UIP_STAT(++uip_stat.udp.chkerr); - UIP_LOG("udp: bad checksum."); - goto drop; - } + dev->d_len -= UIP_IPUDPH_LEN; + dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + if (UDPBUF->udpchksum != 0 && uip_udpchksum(dev) != 0xffff) + { + UIP_STAT(++uip_stat.udp.drop); + UIP_STAT(++uip_stat.udp.chkerr); + UIP_LOG("udp: bad checksum."); + goto drop; + } #else /* UIP_UDP_CHECKSUMS */ - dev->d_len -= UIP_IPUDPH_LEN; + dev->d_len -= UIP_IPUDPH_LEN; #endif /* UIP_UDP_CHECKSUMS */ - /* Demultiplex this UDP packet between the UDP "connections". */ + /* Demultiplex this UDP packet between the UDP "connections". */ - uip_udp_conn = uip_udpactive(UDPBUF); - if (uip_udp_conn) - { - goto udp_found; - } + uip_udp_conn = uip_udpactive(UDPBUF); + if (uip_udp_conn) + { + goto udp_found; + } - UIP_LOG("udp: no matching connection found"); - goto drop; + UIP_LOG("udp: no matching connection found"); + goto drop; - udp_found: - uip_conn = NULL; - uip_flags = UIP_NEWDATA; - dev->d_snddata = dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; - dev->d_sndlen = 0; - uip_udp_callback(dev); +udp_found: + vdbg("udp_found\n"); - udp_send: - if (dev->d_sndlen == 0) - { - goto drop; - } - dev->d_len = dev->d_sndlen + UIP_IPUDPH_LEN; + uip_conn = NULL; + uip_flags = UIP_NEWDATA; + dev->d_snddata = dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + dev->d_sndlen = 0; + uip_udp_callback(dev); + +udp_send: + vdbg("udp_send\n"); + if (dev->d_sndlen == 0) + { + goto drop; + } + dev->d_len = dev->d_sndlen + UIP_IPUDPH_LEN; #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 */ - BUF->ttl = uip_udp_conn->ttl; - BUF->proto = UIP_PROTO_UDP; + BUF->ttl = uip_udp_conn->ttl; + BUF->proto = UIP_PROTO_UDP; - UDPBUF->udplen = HTONS(dev->d_sndlen + UIP_UDPH_LEN); - UDPBUF->udpchksum = 0; + UDPBUF->udplen = HTONS(dev->d_sndlen + UIP_UDPH_LEN); + UDPBUF->udpchksum = 0; - BUF->srcport = uip_udp_conn->lport; - BUF->destport = uip_udp_conn->rport; + BUF->srcport = uip_udp_conn->lport; + BUF->destport = uip_udp_conn->rport; - uiphdr_ipaddr_copy(BUF->srcipaddr, &dev->d_ipaddr); - uiphdr_ipaddr_copy(BUF->destipaddr, &uip_udp_conn->ripaddr); + uiphdr_ipaddr_copy(BUF->srcipaddr, &dev->d_ipaddr); + uiphdr_ipaddr_copy(BUF->destipaddr, &uip_udp_conn->ripaddr); - dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; + dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; #ifdef CONFIG_NET_UDP_CHECKSUMS - /* Calculate UDP checksum. */ - UDPBUF->udpchksum = ~(uip_udpchksum(dev)); - if (UDPBUF->udpchksum == 0) - { - UDPBUF->udpchksum = 0xffff; - } + /* Calculate UDP checksum. */ + + UDPBUF->udpchksum = ~(uip_udpchksum(dev)); + if (UDPBUF->udpchksum == 0) + { + UDPBUF->udpchksum = 0xffff; + } #endif /* UIP_UDP_CHECKSUMS */ - goto ip_send_nolen; + goto ip_send_nolen; #endif /* CONFIG_NET_UDP */ - /* TCP input processing. */ - tcp_input: - UIP_STAT(++uip_stat.tcp.recv); + /* TCP input processing. */ - /* Start of TCP input header processing code. */ +tcp_input: + vdbg("tcp_input\n"); - if (uip_tcpchksum(dev) != 0xffff) - { - /* Compute and check the TCP checksum. */ + UIP_STAT(++uip_stat.tcp.recv); - UIP_STAT(++uip_stat.tcp.drop); - UIP_STAT(++uip_stat.tcp.chkerr); - UIP_LOG("tcp: bad checksum."); - goto drop; - } + /* Start of TCP input header processing code. */ - /* Demultiplex this segment. First check any active connections. */ + if (uip_tcpchksum(dev) != 0xffff) + { + /* Compute and check the TCP checksum. */ - uip_connr = uip_tcpactive(BUF); - if (uip_connr) - { - goto found; - } + UIP_STAT(++uip_stat.tcp.drop); + UIP_STAT(++uip_stat.tcp.chkerr); + UIP_LOG("tcp: bad checksum."); + goto drop; + } - /* 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. - */ + /* Demultiplex this segment. First check any active connections. */ - if ((BUF->flags & TCP_CTL) != TCP_SYN) - { - goto reset; - } + uip_connr = uip_tcpactive(BUF); + if (uip_connr) + { + goto found; + } - tmp16 = BUF->destport; + /* 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. + */ - /* Next, check listening connections. */ - if (uip_islistener(tmp16)) - { - goto found_listen; - } + if ((BUF->flags & TCP_CTL) != TCP_SYN) + { + goto reset; + } - /* No matching connection found, so we send a RST packet. */ - UIP_STAT(++uip_stat.tcp.synrst); - reset: + tmp16 = BUF->destport; - /* We do not send resets in response to resets. */ - if (BUF->flags & TCP_RST) - { - goto drop; - } + /* Next, check listening connections. */ - UIP_STAT(++uip_stat.tcp.rst); + if (uip_islistener(tmp16)) + { + goto found_listen; + } - BUF->flags = TCP_RST | TCP_ACK; - dev->d_len = UIP_IPTCPH_LEN; - BUF->tcpoffset = 5 << 4; + /* No matching connection found, so we send a RST packet. */ - /* Flip the seqno and ackno fields in the TCP header. */ - c = BUF->seqno[3]; - BUF->seqno[3] = BUF->ackno[3]; - BUF->ackno[3] = c; + UIP_STAT(++uip_stat.tcp.synrst); - c = BUF->seqno[2]; - BUF->seqno[2] = BUF->ackno[2]; - BUF->ackno[2] = c; +reset: + vdbg("reset\n"); - c = BUF->seqno[1]; - BUF->seqno[1] = BUF->ackno[1]; - BUF->ackno[1] = c; + /* We do not send resets in response to resets. */ - c = BUF->seqno[0]; - BUF->seqno[0] = BUF->ackno[0]; - BUF->ackno[0] = c; + if (BUF->flags & TCP_RST) + { + goto drop; + } - /* We also have to increase the sequence number we are - acknowledging. If the least significant byte overflowed, we need - to propagate the carry to the other bytes as well. */ - if (++BUF->ackno[3] == 0) - { - if (++BUF->ackno[2] == 0) - { - if (++BUF->ackno[1] == 0) - { - ++BUF->ackno[0]; - } - } - } + UIP_STAT(++uip_stat.tcp.rst); - /* Swap port numbers. */ - tmp16 = BUF->srcport; - BUF->srcport = BUF->destport; - BUF->destport = tmp16; + BUF->flags = TCP_RST | TCP_ACK; + dev->d_len = UIP_IPTCPH_LEN; + BUF->tcpoffset = 5 << 4; - /* Swap IP addresses. */ - uiphdr_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); - uiphdr_ipaddr_copy(BUF->srcipaddr, dev->d_ipaddr); + /* Flip the seqno and ackno fields in the TCP header. */ - /* And send out the RST packet! */ - goto tcp_send_noconn; + seqbyte = BUF->seqno[3]; + BUF->seqno[3] = BUF->ackno[3]; + BUF->ackno[3] = seqbyte; - /* 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. - */ + seqbyte = BUF->seqno[2]; + BUF->seqno[2] = BUF->ackno[2]; + BUF->ackno[2] = seqbyte; + + seqbyte = BUF->seqno[1]; + BUF->seqno[1] = BUF->ackno[1]; + BUF->ackno[1] = seqbyte; + + seqbyte = BUF->seqno[0]; + BUF->seqno[0] = BUF->ackno[0]; + BUF->ackno[0] = seqbyte; + + /* We also have to increase the sequence number we are + * acknowledging. If the least significant byte overflowed, we need + * to propagate the carry to the other bytes as well. + */ + + if (++BUF->ackno[3] == 0) + { + if (++BUF->ackno[2] == 0) + { + if (++BUF->ackno[1] == 0) + { + ++BUF->ackno[0]; + } + } + } + + /* Swap port numbers. */ + + tmp16 = BUF->srcport; + BUF->srcport = BUF->destport; + BUF->destport = tmp16; + + /* Swap IP addresses. */ + + uiphdr_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uiphdr_ipaddr_copy(BUF->srcipaddr, dev->d_ipaddr); + + /* And send out the RST packet! */ + + 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: + vdbg("found_listen\n"); - /* First allocate a new connection structure and see if there is any - * user application to accept it. - */ + /* First allocate a new connection structure and see if there is any + * user application to accept it. + */ - uip_connr = uip_tcpaccept(BUF); - if (uip_connr) - { - /* The connection structure was successfully allocated. Now see - * there is an application waiting to accept the connection (or at - * least queue it it for acceptance). - */ - if (uip_accept(uip_connr, tmp16) != OK) - { - /* No, then we have to give the connection back */ - - uip_tcpfree(uip_connr); - uip_connr = NULL; - } - } - - if (!uip_connr) - { - /* Either (1) all available connections are in use, or (2) there is no - * application in place to accept the connection. We drop packet and hope that - * the remote end will retransmit the packet at a time when we - * have more spare connections or someone waiting to accept the connection. - */ + uip_connr = uip_tcpaccept(BUF); + if (uip_connr) + { + /* The connection structure was successfully allocated. Now see + * there is an application waiting to accept the connection (or at + * least queue it it for acceptance). + */ - UIP_STAT(++uip_stat.tcp.syndrop); - UIP_LOG("tcp: found no unused connections."); - goto drop; - } + if (uip_accept(uip_connr, tmp16) != OK) + { + /* No, then we have to give the connection back */ + + uip_tcpfree(uip_connr); + uip_connr = NULL; + } + } + + if (!uip_connr) + { + /* Either (1) all available connections are in use, or (2) there is no + * application in place to accept the connection. We drop packet and hope that + * the remote end will retransmit the packet at a time when we + * have more spare connections or someone waiting to accept the connection. + */ + + UIP_STAT(++uip_stat.tcp.syndrop); + UIP_LOG("tcp: found no unused connections."); + goto drop; + } - uip_add_rcv_nxt(1); - uip_conn = uip_connr; + uip_add_rcv_nxt(1); + uip_conn = uip_connr; - /* Parse the TCP MSS option, if present. */ + /* Parse the TCP MSS option, if present. */ - if ((BUF->tcpoffset & 0xf0) > 0x50) - { - for (c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) + if ((BUF->tcpoffset & 0xf0) > 0x50) + { + for (i = 0; i < ((BUF->tcpoffset >> 4) - 5) << 2 ;) + { + opt = dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + i]; + if (opt == TCP_OPT_END) + { + /* End of options. */ + + break; + } + else if (opt == TCP_OPT_NOOP) + { + /* NOP option. */ + + ++i; + } + else if (opt == TCP_OPT_MSS && + dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == TCP_OPT_MSS_LEN) + { + /* An MSS option with the right option length. */ + + tmp16 = ((uint16)dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + i] << 8) | + (uint16)dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + i]; + uip_connr->initialmss = uip_connr->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + + break; + } + else + { + /* All other options have a length field, so that we easily + * can skip past them. + */ + + if (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == 0) + { + /* If the length field is zero, the options are malformed + * and we don't process them further. + */ + + break; + } + i += dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i]; + } + } + } + + /* Our response will be a SYNACK. */ + +tcp_send_synack: + vdbg("tcp_send_synack\n"); + BUF->flags = TCP_ACK; + +tcp_send_syn: + vdbg("tcp_send_syn\n"); + BUF->flags |= TCP_SYN; + + /* We send out the TCP Maximum Segment Size option with our SYNACK. */ + + BUF->optdata[0] = TCP_OPT_MSS; + BUF->optdata[1] = TCP_OPT_MSS_LEN; + BUF->optdata[2] = (UIP_TCP_MSS) / 256; + BUF->optdata[3] = (UIP_TCP_MSS) & 255; + dev->d_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; + BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; + goto tcp_send; + + /* This label will be jumped to if we found an active connection. */ + +found: + vdbg("found\n"); + + uip_conn = uip_connr; + uip_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 + * sequence number of this reset is wihtin our advertised window + * before we accept the reset. + */ + + if (BUF->flags & TCP_RST) + { + uip_connr->tcpstateflags = UIP_CLOSED; + vdbg("TCP state: UIP_CLOSED\n"); + UIP_LOG("tcp: got reset, aborting connection."); + + uip_flags = UIP_ABORT; + uip_tcp_callback(dev); + goto drop; + } + + /* Calculated the length of the data, if the application has sent + * any data to us. + */ + + len = (BUF->tcpoffset >> 4) << 2; + + /* d_len will contain the length of the actual TCP data. This is + * calculated by subtracing the length of the TCP header (in + * len) and the length of the IP header (20 bytes). + */ + + dev->d_len -= (len + UIP_IPH_LEN); + + /* First, check if the sequence number of the incoming packet is + * what we're expecting next. If not, we send out an ACK with the + * correct numbers in. + */ + + if (!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && + ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) + { + if ((dev->d_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) && + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || + BUF->seqno[1] != uip_connr->rcv_nxt[1] || + BUF->seqno[2] != uip_connr->rcv_nxt[2] || + BUF->seqno[3] != uip_connr->rcv_nxt[3])) + { + goto tcp_send_ack; + } + } + + /* Next, check if the incoming segment acknowledges any outstanding + * data. If so, we update the sequence number, reset the length of + * the outstanding data, calculate RTT estimations, and reset the + * retransmission timer. + */ + + if ((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) + { + uip_add32(uip_connr->snd_nxt, uip_connr->len); + + if (BUF->ackno[0] == uip_acc32[0] && + BUF->ackno[1] == uip_acc32[1] && + BUF->ackno[2] == uip_acc32[2] && + BUF->ackno[3] == uip_acc32[3]) + { + /* Update sequence number. */ + + uip_connr->snd_nxt[0] = uip_acc32[0]; + uip_connr->snd_nxt[1] = uip_acc32[1]; + uip_connr->snd_nxt[2] = uip_acc32[2]; + uip_connr->snd_nxt[3] = uip_acc32[3]; + + /* Do RTT estimation, unless we have done retransmissions. */ + + if (uip_connr->nrtx == 0) + { + signed char m; + m = uip_connr->rto - uip_connr->timer; + + /* This is taken directly from VJs original code in his paper */ + + m = m - (uip_connr->sa >> 3); + uip_connr->sa += m; + if (m < 0) + { + m = -m; + } + + m = m - (uip_connr->sv >> 2); + uip_connr->sv += m; + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; + } + + /* Set the acknowledged flag. */ + + uip_flags = UIP_ACKDATA; + + /* Reset the retransmission timer. */ + + uip_connr->timer = uip_connr->rto; + + /* Reset length of outstanding data. */ + + uip_connr->len = 0; + } + } + + /* Do different things depending on in what state the connection is. */ + + switch(uip_connr->tcpstateflags & UIP_TS_MASK) + { + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not + * implemented, since we force the application to close when the + * peer sends a FIN (hence the application goes directly from + * ESTABLISHED to LAST_ACK). + */ + + case UIP_SYN_RCVD: + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and + * we are waiting for an ACK that acknowledges the data we sent + * out the last time. Therefore, we want to have the UIP_ACKDATA + * flag set. If so, we enter the ESTABLISHED state. + */ + + if (uip_flags & UIP_ACKDATA) { - opt = dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; - if (opt == TCP_OPT_END) - { - /* End of options. */ - break; - } - else if (opt == TCP_OPT_NOOP) - { - ++c; - /* NOP option. */ - } - else if (opt == TCP_OPT_MSS && - dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_connr->len = 0; + vdbg("TCP state: UIP_ESTABLISHED\n"); + + uip_flags = UIP_CONNECTED; + + if (dev->d_len > 0) { - /* An MSS option with the right option length. */ - tmp16 = ((uint16)dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | - (uint16)dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; - uip_connr->initialmss = uip_connr->mss = - tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; - - /* And we are done processing options. */ - break; + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(dev->d_len); } - else + + dev->d_sndlen = 0; + uip_tcp_callback(dev); + goto appsend; + } + goto drop; + + case UIP_SYN_SENT: + /* In SYN_SENT, we wait for a SYNACK that is sent in response to + * our SYN. The rcv_nxt is set to sequence number in the SYNACK + * plus one, and we send an ACK. We move into the ESTABLISHED + * state. + */ + + if ((uip_flags & UIP_ACKDATA) && + (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) + { + /* Parse the TCP MSS option, if present. */ + + if ((BUF->tcpoffset & 0xf0) > 0x50) { - /* All other options have a length field, so that we easily - can skip past them. */ - if (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) + for (i = 0; i < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { - /* If the length field is zero, the options are malformed - and we don't process them further. */ - break; + opt = dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + i]; + if (opt == TCP_OPT_END) + { + /* End of options. */ + + break; + } + else if (opt == TCP_OPT_NOOP) + { + /* NOP option. */ + + ++i; + } + else if (opt == TCP_OPT_MSS && + dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == TCP_OPT_MSS_LEN) + { + /* An MSS option with the right option length. */ + + tmp16 = + (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + i] << 8) | + dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + i]; + uip_connr->initialmss = + uip_connr->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + + break; + } + else + { + /* All other options have a length field, so that we + * easily can skip past them. + */ + + if (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == 0) + { + /* If the length field is zero, the options are + * malformed and we don't process them further. + */ + + break; + } + i += dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i]; + } } - c += dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; } + + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + vdbg("TCP state: UIP_ESTABLISHED\n"); + + uip_add_rcv_nxt(1); + uip_flags = UIP_CONNECTED | UIP_NEWDATA; + uip_connr->len = 0; + dev->d_len = 0; + dev->d_sndlen = 0; + uip_tcp_callback(dev); + goto appsend; } - } - /* Our response will be a SYNACK. */ -tcp_send_synack: - BUF->flags = TCP_ACK; - - tcp_send_syn: - BUF->flags |= TCP_SYN; - - /* We send out the TCP Maximum Segment Size option with our - SYNACK. */ - BUF->optdata[0] = TCP_OPT_MSS; - BUF->optdata[1] = TCP_OPT_MSS_LEN; - BUF->optdata[2] = (UIP_TCP_MSS) / 256; - BUF->optdata[3] = (UIP_TCP_MSS) & 255; - dev->d_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; - BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; - goto tcp_send; - - /* This label will be jumped to if we found an active connection. */ - found: - uip_conn = uip_connr; - uip_flags = 0; - - /* We do a very naive form of TCP reset processing; we just accept - * any RST and kill our connection. We should in fact check if the - * sequence number of this reset is wihtin our advertised window - * before we accept the reset. - */ + /* Inform the application that the connection failed */ - if (BUF->flags & TCP_RST) - { - uip_connr->tcpstateflags = UIP_CLOSED; - UIP_LOG("tcp: got reset, aborting connection."); uip_flags = UIP_ABORT; uip_tcp_callback(dev); - goto drop; - } - /* Calculated the length of the data, if the application has sent - * any data to us. - */ + /* The connection is closed after we send the RST */ - c = (BUF->tcpoffset >> 4) << 2; + uip_conn->tcpstateflags = UIP_CLOSED; + vdbg("TCP state: UIP_CLOSED\n"); + goto reset; - /* d_len will contain the length of the actual TCP data. This is - * calculated by subtracing the length of the TCP header (in - * c) and the length of the IP header (20 bytes). - */ + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application to feed + * data into the d_buf. If the UIP_ACKDATA flag is set, the + * application should put new data into the buffer, otherwise we are + * retransmitting an old segment, and the application should put that + * data into the buffer. + * + * If the incoming packet is a FIN, we should close the connection on + * this side as well, and we send out a FIN and enter the LAST_ACK + * state. We require that there is no outstanding data; otherwise the + * sequence numbers will be screwed up. + */ - dev->d_len -= (c + UIP_IPH_LEN); + if (BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) + { + if (uip_outstanding(uip_connr)) + { + goto drop; + } - /* First, check if the sequence number of the incoming packet is - * what we're expecting next. If not, we send out an ACK with the - * correct numbers in. - */ + uip_add_rcv_nxt(dev->d_len + 1); + uip_flags |= UIP_CLOSE; - if (!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && - ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) - { - if ((dev->d_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) && - (BUF->seqno[0] != uip_connr->rcv_nxt[0] || - BUF->seqno[1] != uip_connr->rcv_nxt[1] || - BUF->seqno[2] != uip_connr->rcv_nxt[2] || - BUF->seqno[3] != uip_connr->rcv_nxt[3])) + if (dev->d_len > 0) + { + uip_flags |= UIP_NEWDATA; + } + + uip_tcp_callback(dev); + + uip_connr->tcpstateflags = UIP_LAST_ACK; + uip_connr->len = 1; + uip_connr->nrtx = 0; + vdbg("TCP state: UIP_LAST_ACK\n"); + +tcp_send_finack: + vdbg("tcp_send_finack\n"); + + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* Check the URG flag. If this is set, the segment carries urgent + data that we must pass to the application. */ + if ((BUF->flags & TCP_URG) != 0) { - goto tcp_send_ack; +#if UIP_URGDATA > 0 + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; + if (uip_urglen > dev->d_len) + { + /* There is more urgent data in the next segment to come. */ + + uip_urglen = dev->d_len; + } + + uip_add_rcv_nxt(uip_urglen); + dev->d_len -= uip_urglen; + uip_urgdata = dev->d_appdata; + dev->d_appdata += uip_urglen; + } + else + { + uip_urglen = 0; +#else /* UIP_URGDATA > 0 */ + dev->d_appdata = + ((uint8*)dev->d_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]); + dev->d_len -= + (BUF->urgp[0] << 8) | BUF->urgp[1]; +#endif /* UIP_URGDATA > 0 */ } - } - /* Next, check if the incoming segment acknowledges any outstanding - data. If so, we update the sequence number, reset the length of - the outstanding data, calculate RTT estimations, and reset the - retransmission timer. */ - if ((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) - { - uip_add32(uip_connr->snd_nxt, uip_connr->len); + /* If d_len > 0 we have TCP data in the packet, and we flag this + * by setting the UIP_NEWDATA flag and update the sequence number + * we acknowledge. If the application has stopped the dataflow + * using uip_stop(), we must not accept any data packets from the + * remote host. + */ + + if (dev->d_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) + { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(dev->d_len); + } + + /* Check if the available buffer space advertised by the other end + * is smaller than the initial MSS for this connection. If so, we + * set the current MSS to the window size to ensure that the + * application does not send more data than the other end can + * handle. + * + * If the remote host advertises a zero window, we set the MSS to + * the initial MSS so that the application will send an entire MSS + * of data. This data will not be acknowledged by the receiver, + * and the application will retransmit it. This is called the + * "persistent timer" and uses the retransmission mechanim. + */ + + tmp16 = ((uint16)BUF->wnd[0] << 8) + (uint16)BUF->wnd[1]; + if (tmp16 > uip_connr->initialmss || tmp16 == 0) + { + tmp16 = uip_connr->initialmss; + } + uip_connr->mss = tmp16; + + /* If this packet constitutes an ACK for outstanding data (flagged + * by the UIP_ACKDATA flag, we should call the application since it + * might want to send more data. If the incoming packet had data + * from the peer (as flagged by the UIP_NEWDATA flag), the + * application must also be notified. + * + * When the application is called, the d_len field + * contains the length of the incoming data. The application can + * access the incoming data through the global pointer + * d_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN + * bytes into the d_buf array. + * + * If the application wishes to send any data, this data should be + * put into the d_appdata and the length of the data should be + * put into d_len. If the application don't have any data to + * send, d_len must be set to 0. + */ - if (BUF->ackno[0] == uip_acc32[0] && - BUF->ackno[1] == uip_acc32[1] && - BUF->ackno[2] == uip_acc32[2] && - BUF->ackno[3] == uip_acc32[3]) + if (uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { - /* Update sequence number. */ - uip_connr->snd_nxt[0] = uip_acc32[0]; - uip_connr->snd_nxt[1] = uip_acc32[1]; - uip_connr->snd_nxt[2] = uip_acc32[2]; - uip_connr->snd_nxt[3] = uip_acc32[3]; - - /* Do RTT estimation, unless we have done retransmissions. */ - if (uip_connr->nrtx == 0) + dev->d_sndlen = 0; + uip_tcp_callback(dev); + +appsend: + vdbg("appsend\n"); + + if (uip_flags & UIP_ABORT) { - signed char m; - m = uip_connr->rto - uip_connr->timer; + dev->d_sndlen = 0; + uip_connr->tcpstateflags = UIP_CLOSED; + vdbg("TCP state: UIP_CLOSED\n"); + + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + if (uip_flags & UIP_CLOSE) + { + uip_connr->tcpstateflags = UIP_FIN_WAIT_1; + uip_connr->len = 1; + uip_connr->nrtx = 0; + vdbg("TCP state: UIP_FIN_WAIT_1\n"); + + BUF->flags = TCP_FIN | TCP_ACK; + dev->d_sndlen = 0; + goto tcp_send_nodata; + } + + /* If d_sndlen > 0, the application has data to be sent. */ + + if (dev->d_sndlen > 0) + { + /* If the connection has acknowledged data, the contents of + * the ->len variable should be discarded. + */ + + if ((uip_flags & UIP_ACKDATA) != 0) + { + uip_connr->len = 0; + } + + /* If the ->len variable is non-zero the connection has + * already data in transit and cannot send anymore right + * now. + */ + + if (uip_connr->len == 0) + { + /* The application cannot send more than what is + * allowed by the mss (the minumum of the MSS and the + * available window). + */ + + if (dev->d_sndlen > uip_connr->mss) + { + dev->d_sndlen = uip_connr->mss; + } - /* This is taken directly from VJs original code in his paper */ - m = m - (uip_connr->sa >> 3); - uip_connr->sa += m; - if (m < 0) + /* Remember how much data we send out now so that we + * know when everything has been acknowledged. + */ + + uip_connr->len = dev->d_sndlen; + } + else { - m = -m; + /* If the application already had unacknowledged data, + * we make sure that the application does not send + * (i.e., retransmit) out more than it previously sent + * out. + */ + + dev->d_sndlen = uip_connr->len; } - m = m - (uip_connr->sv >> 2); - uip_connr->sv += m; - uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; } + uip_connr->nrtx = 0; +apprexmit: + vdbg("apprexmit\n"); + dev->d_appdata = dev->d_snddata; - /* Set the acknowledged flag. */ - uip_flags = UIP_ACKDATA; + /* If the application has data to be sent, or if the incoming + * packet had new data in it, we must send out a packet. + */ - /* Reset the retransmission timer. */ - uip_connr->timer = uip_connr->rto; + if (dev->d_sndlen > 0 && uip_connr->len > 0) + { + /* Add the length of the IP and TCP headers. */ - /* Reset length of outstanding data. */ - uip_connr->len = 0; - } - } + dev->d_len = uip_connr->len + UIP_TCPIP_HLEN; - /* Do different things depending on in what state the connection is. */ - switch(uip_connr->tcpstateflags & UIP_TS_MASK) - { - /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not - implemented, since we force the application to close when the - peer sends a FIN (hence the application goes directly from - ESTABLISHED to LAST_ACK). */ - case UIP_SYN_RCVD: - /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and - * we are waiting for an ACK that acknowledges the data we sent - * out the last time. Therefore, we want to have the UIP_ACKDATA - * flag set. If so, we enter the ESTABLISHED state. - */ + /* We always set the ACK flag in response packets. */ - if (uip_flags & UIP_ACKDATA) - { - uip_connr->tcpstateflags = UIP_ESTABLISHED; - uip_flags = UIP_CONNECTED; - uip_connr->len = 0; + BUF->flags = TCP_ACK | TCP_PSH; - if (dev->d_len > 0) - { - uip_flags |= UIP_NEWDATA; - uip_add_rcv_nxt(dev->d_len); - } + /* Send the packet. */ - dev->d_sndlen = 0; - uip_tcp_callback(dev); - goto appsend; - } - goto drop; + goto tcp_send_noopts; + } - case UIP_SYN_SENT: - /* In SYN_SENT, we wait for a SYNACK that is sent in response to - our SYN. The rcv_nxt is set to sequence number in the SYNACK - plus one, and we send an ACK. We move into the ESTABLISHED - state. */ - if ((uip_flags & UIP_ACKDATA) && - (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) - { - /* Parse the TCP MSS option, if present. */ - if ((BUF->tcpoffset & 0xf0) > 0x50) - { - for (c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) - { - opt = dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; - if (opt == TCP_OPT_END) - { - /* End of options. */ - break; - } - else if (opt == TCP_OPT_NOOP) - { - ++c; - /* NOP option. */ - } - else if (opt == TCP_OPT_MSS && - dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) - { - /* An MSS option with the right option length. */ - tmp16 = (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | - dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; - uip_connr->initialmss = - uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; - - /* And we are done processing options. */ - break; - } - else - { - /* All other options have a length field, so that we easily - can skip past them. */ - if (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) - { - /* If the length field is zero, the options are malformed - and we don't process them further. */ - break; - } - c += dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; - } - } - } + /* If there is no data to send, just send out a pure ACK if + * there is newdata. + */ - uip_connr->tcpstateflags = UIP_ESTABLISHED; - uip_connr->rcv_nxt[0] = BUF->seqno[0]; - uip_connr->rcv_nxt[1] = BUF->seqno[1]; - uip_connr->rcv_nxt[2] = BUF->seqno[2]; - uip_connr->rcv_nxt[3] = BUF->seqno[3]; - uip_add_rcv_nxt(1); - uip_flags = UIP_CONNECTED | UIP_NEWDATA; - uip_connr->len = 0; - dev->d_len = 0; - dev->d_sndlen = 0; - uip_tcp_callback(dev); - goto appsend; - } + if (uip_flags & UIP_NEWDATA) + { + dev->d_len = UIP_TCPIP_HLEN; + BUF->flags = TCP_ACK; + goto tcp_send_noopts; + } + } + goto drop; - /* Inform the application that the connection failed */ - uip_flags = UIP_ABORT; - uip_tcp_callback(dev); + case UIP_LAST_ACK: + /* We can close this connection if the peer has acknowledged our + * FIN. This is indicated by the UIP_ACKDATA flag. + */ - /* The connection is closed after we send the RST */ - uip_conn->tcpstateflags = UIP_CLOSED; - goto reset; + if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_CLOSED; + vdbg("TCP state: UIP_CLOSED\n"); - case UIP_ESTABLISHED: - /* In the ESTABLISHED state, we call upon the application to feed - data into the d_buf. If the UIP_ACKDATA flag is set, the - application should put new data into the buffer, otherwise we are - retransmitting an old segment, and the application should put that - data into the buffer. + uip_flags = UIP_CLOSE; + uip_tcp_callback(dev); + } + break; - If the incoming packet is a FIN, we should close the connection on - this side as well, and we send out a FIN and enter the LAST_ACK - state. We require that there is no outstanding data; otherwise the - sequence numbers will be screwed up. */ + case UIP_FIN_WAIT_1: + /* The application has closed the connection, but the remote host + * hasn't closed its end yet. Thus we do nothing but wait for a + * FIN from the other side. + */ - if (BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) - { - if (uip_outstanding(uip_connr)) - { - goto drop; - } + if (dev->d_len > 0) + { + uip_add_rcv_nxt(dev->d_len); + } + if (BUF->flags & TCP_FIN) + { + if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_connr->len = 0; + vdbg("TCP state: UIP_TIME_WAIT\n"); + } + else + { + uip_connr->tcpstateflags = UIP_CLOSING; + vdbg("TCP state: UIP_CLOSING\n"); + } - uip_add_rcv_nxt(dev->d_len + 1); - uip_flags |= UIP_CLOSE; + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + uip_tcp_callback(dev); + goto tcp_send_ack; + } + else if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_FIN_WAIT_2; + uip_connr->len = 0; + vdbg("TCP state: UIP_FIN_WAIT_2\n"); + goto drop; + } - if (dev->d_len > 0) - { - uip_flags |= UIP_NEWDATA; - } + if (dev->d_len > 0) + { + goto tcp_send_ack; + } + goto drop; - uip_tcp_callback(dev); - uip_connr->len = 1; - uip_connr->tcpstateflags = UIP_LAST_ACK; - uip_connr->nrtx = 0; + case UIP_FIN_WAIT_2: + if (dev->d_len > 0) + { + uip_add_rcv_nxt(dev->d_len); + } - tcp_send_finack: - BUF->flags = TCP_FIN | TCP_ACK; - goto tcp_send_nodata; - } + if (BUF->flags & TCP_FIN) + { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + vdbg("TCP state: UIP_TIME_WAIT\n"); - /* Check the URG flag. If this is set, the segment carries urgent - data that we must pass to the application. */ - if ((BUF->flags & TCP_URG) != 0) - { -#if UIP_URGDATA > 0 - uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; - if (uip_urglen > dev->d_len) - { - /* There is more urgent data in the next segment to come. */ - uip_urglen = dev->d_len; - } - uip_add_rcv_nxt(uip_urglen); - dev->d_len -= uip_urglen; - uip_urgdata = dev->d_appdata; - dev->d_appdata += uip_urglen; - } - else - { - uip_urglen = 0; -#else /* UIP_URGDATA > 0 */ - dev->d_appdata = ((uint8*)dev->d_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]); - dev->d_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; -#endif /* UIP_URGDATA > 0 */ - } + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + uip_tcp_callback(dev); + goto tcp_send_ack; + } - /* If d_len > 0 we have TCP data in the packet, and we flag this - by setting the UIP_NEWDATA flag and update the sequence number - we acknowledge. If the application has stopped the dataflow - using uip_stop(), we must not accept any data packets from the - remote host. */ - if (dev->d_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) - { - uip_flags |= UIP_NEWDATA; - uip_add_rcv_nxt(dev->d_len); - } + if (dev->d_len > 0) + { + goto tcp_send_ack; + } + goto drop; - /* Check if the available buffer space advertised by the other end - is smaller than the initial MSS for this connection. If so, we - set the current MSS to the window size to ensure that the - application does not send more data than the other end can - handle. - - If the remote host advertises a zero window, we set the MSS to - the initial MSS so that the application will send an entire MSS - of data. This data will not be acknowledged by the receiver, - and the application will retransmit it. This is called the - "persistent timer" and uses the retransmission mechanim. - */ - tmp16 = ((uint16)BUF->wnd[0] << 8) + (uint16)BUF->wnd[1]; - if (tmp16 > uip_connr->initialmss || tmp16 == 0) - { - tmp16 = uip_connr->initialmss; - } - uip_connr->mss = tmp16; - - /* If this packet constitutes an ACK for outstanding data (flagged - by the UIP_ACKDATA flag, we should call the application since it - might want to send more data. If the incoming packet had data - from the peer (as flagged by the UIP_NEWDATA flag), the - application must also be notified. - - When the application is called, the d_len field - contains the length of the incoming data. The application can - access the incoming data through the global pointer - d_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN - bytes into the d_buf array. - - If the application wishes to send any data, this data should be - put into the d_appdata and the length of the data should be - put into d_len. If the application don't have any data to - send, d_len must be set to 0. */ - if (uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) - { - dev->d_sndlen = 0; - uip_tcp_callback(dev); + case UIP_TIME_WAIT: + goto tcp_send_ack; - appsend: - if (uip_flags & UIP_ABORT) - { - dev->d_sndlen = 0; - uip_connr->tcpstateflags = UIP_CLOSED; - BUF->flags = TCP_RST | TCP_ACK; - goto tcp_send_nodata; - } + case UIP_CLOSING: + if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + vdbg("TCP state: UIP_TIME_WAIT\n"); + } + } + goto drop; - if (uip_flags & UIP_CLOSE) - { - dev->d_sndlen = 0; - uip_connr->len = 1; - uip_connr->tcpstateflags = UIP_FIN_WAIT_1; - uip_connr->nrtx = 0; - BUF->flags = TCP_FIN | TCP_ACK; - goto tcp_send_nodata; - } + /* We jump here when we are ready to send the packet, and just want + * to set the appropriate TCP sequence numbers in the TCP header. + */ - /* If d_sndlen > 0, the application has data to be sent. */ - if (dev->d_sndlen > 0) - { - /* If the connection has acknowledged data, the contents of - the ->len variable should be discarded. */ - if ((uip_flags & UIP_ACKDATA) != 0) - { - uip_connr->len = 0; - } - - /* If the ->len variable is non-zero the connection has - already data in transit and cannot send anymore right - now. */ - if (uip_connr->len == 0) - { - /* The application cannot send more than what is allowed by - the mss (the minumum of the MSS and the available - window). */ - if (dev->d_sndlen > uip_connr->mss) - { - dev->d_sndlen = uip_connr->mss; - } - - /* Remember how much data we send out now so that we know - when everything has been acknowledged. */ - uip_connr->len = dev->d_sndlen; - } - else - { - /* If the application already had unacknowledged data, we - make sure that the application does not send (i.e., - retransmit) out more than it previously sent out. */ - dev->d_sndlen = uip_connr->len; - } - } - uip_connr->nrtx = 0; - apprexmit: - dev->d_appdata = dev->d_snddata; +tcp_send_ack: + vdbg("tcp_send_ack\n"); - /* If the application has data to be sent, or if the incoming - packet had new data in it, we must send out a packet. */ - if (dev->d_sndlen > 0 && uip_connr->len > 0) - { - /* Add the length of the IP and TCP headers. */ - dev->d_len = uip_connr->len + UIP_TCPIP_HLEN; + BUF->flags = TCP_ACK; - /* We always set the ACK flag in response packets. */ - BUF->flags = TCP_ACK | TCP_PSH; +tcp_send_nodata: + vdbg("tcp_send_nodata\n"); - /* Send the packet. */ - goto tcp_send_noopts; - } + dev->d_len = UIP_IPTCPH_LEN; + tcp_send_noopts: + BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; - /* If there is no data to send, just send out a pure ACK if - there is newdata. */ - if (uip_flags & UIP_NEWDATA) - { - dev->d_len = UIP_TCPIP_HLEN; - BUF->flags = TCP_ACK; - goto tcp_send_noopts; - } - } - goto drop; +tcp_send: + vdbg("tcp_send\n"); - case UIP_LAST_ACK: - /* We can close this connection if the peer has acknowledged our - FIN. This is indicated by the UIP_ACKDATA flag. */ - if (uip_flags & UIP_ACKDATA) - { - uip_connr->tcpstateflags = UIP_CLOSED; - uip_flags = UIP_CLOSE; - uip_tcp_callback(dev); - } - break; + /* We're done with the input processing. We are now ready to send a + * reply. Our job is to fill in all the fields of the TCP and IP + * headers before calculating the checksum and finally send the + * packet. + */ - case UIP_FIN_WAIT_1: - /* The application has closed the connection, but the remote host - hasn't closed its end yet. Thus we do nothing but wait for a - FIN from the other side. */ - if (dev->d_len > 0) - { - uip_add_rcv_nxt(dev->d_len); - } - if (BUF->flags & TCP_FIN) - { - if (uip_flags & UIP_ACKDATA) - { - uip_connr->tcpstateflags = UIP_TIME_WAIT; - uip_connr->timer = 0; - uip_connr->len = 0; - } - else - { - uip_connr->tcpstateflags = UIP_CLOSING; - } + BUF->ackno[0] = uip_connr->rcv_nxt[0]; + BUF->ackno[1] = uip_connr->rcv_nxt[1]; + BUF->ackno[2] = uip_connr->rcv_nxt[2]; + BUF->ackno[3] = uip_connr->rcv_nxt[3]; - uip_add_rcv_nxt(1); - uip_flags = UIP_CLOSE; - uip_tcp_callback(dev); - goto tcp_send_ack; - } - else if (uip_flags & UIP_ACKDATA) - { - uip_connr->tcpstateflags = UIP_FIN_WAIT_2; - uip_connr->len = 0; - goto drop; - } - if (dev->d_len > 0) - { - goto tcp_send_ack; - } - goto drop; + BUF->seqno[0] = uip_connr->snd_nxt[0]; + BUF->seqno[1] = uip_connr->snd_nxt[1]; + BUF->seqno[2] = uip_connr->snd_nxt[2]; + BUF->seqno[3] = uip_connr->snd_nxt[3]; - case UIP_FIN_WAIT_2: - if (dev->d_len > 0) - { - uip_add_rcv_nxt(dev->d_len); - } - if (BUF->flags & TCP_FIN) - { - uip_connr->tcpstateflags = UIP_TIME_WAIT; - uip_connr->timer = 0; - uip_add_rcv_nxt(1); - uip_flags = UIP_CLOSE; - uip_tcp_callback(dev); - goto tcp_send_ack; - } - if (dev->d_len > 0) - { - goto tcp_send_ack; - } - goto drop; + BUF->proto = UIP_PROTO_TCP; - case UIP_TIME_WAIT: - goto tcp_send_ack; + BUF->srcport = uip_connr->lport; + BUF->destport = uip_connr->rport; - case UIP_CLOSING: - if (uip_flags & UIP_ACKDATA) - { - uip_connr->tcpstateflags = UIP_TIME_WAIT; - uip_connr->timer = 0; - } - } - goto drop; - - /* We jump here when we are ready to send the packet, and just want - to set the appropriate TCP sequence numbers in the TCP header. */ - tcp_send_ack: - BUF->flags = TCP_ACK; - tcp_send_nodata: - dev->d_len = UIP_IPTCPH_LEN; - tcp_send_noopts: - BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; - tcp_send: - /* We're done with the input processing. We are now ready to send a - reply. Our job is to fill in all the fields of the TCP and IP - headers before calculating the checksum and finally send the - packet. */ - BUF->ackno[0] = uip_connr->rcv_nxt[0]; - BUF->ackno[1] = uip_connr->rcv_nxt[1]; - BUF->ackno[2] = uip_connr->rcv_nxt[2]; - BUF->ackno[3] = uip_connr->rcv_nxt[3]; - - BUF->seqno[0] = uip_connr->snd_nxt[0]; - BUF->seqno[1] = uip_connr->snd_nxt[1]; - BUF->seqno[2] = uip_connr->snd_nxt[2]; - BUF->seqno[3] = uip_connr->snd_nxt[3]; - - BUF->proto = UIP_PROTO_TCP; - - BUF->srcport = uip_connr->lport; - BUF->destport = uip_connr->rport; - - uiphdr_ipaddr_copy(BUF->srcipaddr, &dev->d_ipaddr); - uiphdr_ipaddr_copy(BUF->destipaddr, &uip_connr->ripaddr); - - if (uip_connr->tcpstateflags & UIP_STOPPED) - { - /* If the connection has issued uip_stop(), we advertise a zero - window so that the remote host will stop sending data. */ - BUF->wnd[0] = BUF->wnd[1] = 0; - } - else - { - BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); - BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); - } + uiphdr_ipaddr_copy(BUF->srcipaddr, &dev->d_ipaddr); + uiphdr_ipaddr_copy(BUF->destipaddr, &uip_connr->ripaddr); + + if (uip_connr->tcpstateflags & UIP_STOPPED) + { + /* If the connection has issued uip_stop(), we advertise a zero + * window so that the remote host will stop sending data. + */ - tcp_send_noconn: - BUF->ttl = UIP_TTL; + BUF->wnd[0] = BUF->wnd[1] = 0; + } + else + { + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); + } + +tcp_send_noconn: + vdbg("tcp_send_noconn\n"); + + BUF->ttl = UIP_TTL; #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 */ - BUF->urgp[0] = BUF->urgp[1] = 0; + BUF->urgp[0] = BUF->urgp[1] = 0; + + /* Calculate TCP checksum. */ - /* Calculate TCP checksum. */ - BUF->tcpchksum = 0; - BUF->tcpchksum = ~(uip_tcpchksum(dev)); + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum(dev)); #ifdef CONFIG_NET_UDP - ip_send_nolen: +ip_send_nolen: + vdbg("ip_send_nolen\n"); #endif /* CONFIG_NET_UDP */ #ifdef CONFIG_NET_IPv6 - BUF->vtc = 0x60; - BUF->tcflow = 0x00; - BUF->flow = 0x00; + BUF->vtc = 0x60; + BUF->tcflow = 0x00; + BUF->flow = 0x00; #else /* CONFIG_NET_IPv6 */ - BUF->vhl = 0x45; - BUF->tos = 0; - BUF->ipoffset[0] = BUF->ipoffset[1] = 0; - ++ipid; - BUF->ipid[0] = ipid >> 8; - BUF->ipid[1] = ipid & 0xff; - - /* Calculate IP checksum. */ - BUF->ipchksum = 0; - BUF->ipchksum = ~(uip_ipchksum(dev)); - dbg("ip_send_nolen checksum: 0x%04x\n", uip_ipchksum(dev)); + BUF->vhl = 0x45; + BUF->tos = 0; + BUF->ipoffset[0] = 0; + BUF->ipoffset[1] = 0; + ++g_ipid; + BUF->ipid[0] = g_ipid >> 8; + BUF->ipid[1] = g_ipid & 0xff; + + /* Calculate IP checksum. */ + + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum(dev)); + vdbg("checksum: 0x%04x\n", uip_ipchksum(dev)); #endif /* CONFIG_NET_IPv6 */ - UIP_STAT(++uip_stat.tcp.sent); - send: - dbg("Sending packet with length %d (%d)\n", dev->d_len, - (BUF->len[0] << 8) | BUF->len[1]); + UIP_STAT(++uip_stat.tcp.sent); - UIP_STAT(++uip_stat.ip.sent); +send: + vdbg("send: packet length %d (%d)\n", + dev->d_len, (BUF->len[0] << 8) | BUF->len[1]); - /* Return and let the caller do the actual transmission. */ - uip_flags = 0; - return; - drop: - dev->d_len = 0; - uip_flags = 0; - return; + UIP_STAT(++uip_stat.ip.sent); + + /* Return and let the caller do the actual transmission. */ + + uip_flags = 0; + return; + +drop: + dev->d_len = 0; + uip_flags = 0; + return; } +#endif /* CONFIG_NET */ + diff --git a/nuttx/netutils/telnetd/telnetd.c b/nuttx/netutils/telnetd/telnetd.c index 6d4ba2e7b..075393484 100644 --- a/nuttx/netutils/telnetd/telnetd.c +++ b/nuttx/netutils/telnetd/telnetd.c @@ -306,7 +306,7 @@ void uip_interrupt_event(struct uip_driver_s *dev, void *private) { #warning OBSOLETE -- needs to be redesigned unsigned int i; - if (uip_connected()) + if (uip_connected_event()) { for (i = 0; i < TELNETD_CONF_NUMLINES; ++i) { @@ -325,22 +325,23 @@ void uip_interrupt_event(struct uip_driver_s *dev, void *private) return; } - if (uip_closed() || uip_aborted() || uip_timedout()) + if (uip_close_event() || uip_abort_event() || uip_timeout_event()) { closed(); } - if (uip_acked()) + if (uip_ack_event()) { acked(); } - if (uip_newdata()) + if (uip_newdata_event()) { newdata(dev); } - if (uip_rexmit() || uip_newdata() || uip_acked() || uip_connected() || uip_poll()) + if (uip_rexmit_event() || uip_newdata_event() || uip_ack_event() || + uip_connected_event() || uip_poll_event()) { senddata(dev); } diff --git a/nuttx/netutils/webclient/webclient.c b/nuttx/netutils/webclient/webclient.c index 56c430881..f285c3f41 100644 --- a/nuttx/netutils/webclient/webclient.c +++ b/nuttx/netutils/webclient/webclient.c @@ -407,7 +407,7 @@ static void newdata(struct uip_driver_s *dev) void uip_interrupt_event(struct uip_driver_s *dev) { #warning OBSOLETE -- needs to be redesigned - if (uip_connected()) + if (uip_connected_event()) { s.timer = 0; s.state = WEBCLIENT_STATE_STATUSLINE; @@ -423,33 +423,33 @@ void uip_interrupt_event(struct uip_driver_s *dev) return; } - if (uip_aborted()) + if (uip_abort_event()) { webclient_aborted(); } - if (uip_timedout()) + if (uip_timeout_event()) { webclient_timedout(); } - if (uip_acked()) + if (uip_ack_event()) { s.timer = 0; acked(); } - if (uip_newdata()) + if (uip_newdata_event()) { s.timer = 0; newdata(dev); } - if (uip_rexmit() || uip_newdata() || uip_acked()) + if (uip_rexmit_event() || uip_newdata_event() || uip_ack_event()) { senddata(dev); } - else if (uip_poll()) + else if (uip_poll_event()) { ++s.timer; if (s.timer == WEBCLIENT_TIMEOUT) @@ -460,7 +460,7 @@ void uip_interrupt_event(struct uip_driver_s *dev) } } - if (uip_closed()) + if (uip_close_event()) { if (s.httpflag != HTTPFLAG_MOVED) { |