Basic TCP send functional

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@371 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2007-11-05 23:04:16 +00:00
parent 77119d8359
commit 44778c69bd
19 changed files with 1646 additions and 1273 deletions
+13 -1
View File
@@ -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)
{
+26 -5
View File
@@ -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 */
+15 -2
View File
@@ -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);
+1 -1
View File
@@ -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
+10 -6
View File
@@ -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 */
+2
View File
@@ -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 **************************************************/
+161
View File
@@ -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 */
+41 -26
View File
@@ -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.
@@ -340,6 +354,30 @@ struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf)
return conn;
}
/****************************************************************************
* 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()
*
@@ -417,29 +455,6 @@ struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf)
return conn;
}
/****************************************************************************
* 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()
*
+19 -18
View File
@@ -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.
+1187 -1015
View File
File diff suppressed because it is too large Load Diff