Add send() timeout logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@420 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-12-02 15:11:32 +00:00
parent 929a52b3e0
commit 4c54d7d07e
5 changed files with 92 additions and 38 deletions

View file

@ -265,3 +265,4 @@
* Fix UDP recvfrom timeout bug
* Correct processing of input UDP broadcast packets.
* Verfied basic DHCP client functionality (netutils/dhcpc)
* Implemented send() timeout logic

View file

@ -753,6 +753,7 @@ Other memory:
* Fix UDP recvfrom timeout bug
* Correct processing of input UDP broadcast packets.
* Verfied basic DHCP client functionality (netutils/dhcpc)
* Implemented send() timeout logic
</pre></ul>
<table width ="100%">

7
TODO
View file

@ -29,10 +29,8 @@ o C++ Support
- Need to call static constructors
o Network
- Did not implement send() and sendto() timeouts. Option is setable via setsockopt,
but is not implemented.
- uIP's netutils/smtp, dpcpc, resolv, webclient -- untested
- Should implement SOCK_RAW
- uIP's netutils/smtp, resolv, webclient -- untested
- Should implement SOCK_RAW, SOCK_PACKET
- uIP polling issues:
(1) Current logic will not support multiple ethernet drivers. Each driver should
poll on TCP connections connect on the network supported by the driver; UDP
@ -44,6 +42,7 @@ o Network
- uIP/Socket callback logic is not thread safe. This means that a socket cannot be
used concurrently by two threads. Minimal fix: Add mutex to support exclusion.
- IPv6 support is incomplete
- Incoming UDP broadcast should only be accepted if listening on INADDR_ANY(?)
o USB
- Implement USB device support

View file

@ -111,12 +111,7 @@ static inline void accept_tcpsender(struct uip_conn *conn, struct accept_s *psta
{
addr->sin_family = AF_INET;
addr->sin_port = conn->rport;
#ifdef CONFIG_NET_IPv6
uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr);
#else
uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr);
#endif
}
}
#endif
@ -400,4 +395,4 @@ errout:
return ERROR;
}
#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP*/
#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP */

View file

@ -75,6 +75,9 @@ struct send_s
ssize_t snd_sent; /* The number of bytes sent */
uint32 snd_isn; /* Initial sequence number */
uint32 snd_acked; /* The number of bytes acked */
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
uint32 snd_time; /* last send time for determining timeout */
#endif
};
/****************************************************************************
@ -129,6 +132,46 @@ static uint32 send_getackno(struct uip_driver_s *dev)
return ntohl(tmp);
}
/****************************************************************************
* Function: send_timeout
*
* Description:
* Check for send timeout.
*
* Parameters:
* pstate send state structure
*
* Returned Value:
* TRUE:timeout FALSE:no timeout
*
* Assumptions:
* Running at the interrupt level
*
****************************************************************************/
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
static inline int send_timeout(struct send_s *pstate)
{
FAR struct socket *psock = 0;
/* Check for a timeout configured via setsockopts(SO_SNDTIMEO).
* If none... we well let the send wait forever.
*/
psock = pstate->snd_sock;
if (psock && psock->s_sndtimeo != 0)
{
/* Check if the configured timeout has elapsed */
return net_timeo(pstate->snd_time, psock->s_sndtimeo);
}
/* No timeout */
return FALSE;
}
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
/****************************************************************************
* Function: send_interrupt
*
@ -149,7 +192,8 @@ static uint32 send_getackno(struct uip_driver_s *dev)
*
****************************************************************************/
static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn,
uint8 flags)
{
struct send_s *pstate = (struct send_s *)conn->data_private;
@ -161,10 +205,10 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
if ((flags & UIP_ACKDATA) != 0)
{
/* The current acknowledgement number number is the (relative) offset of
* the of the next byte needed by the receiver. The snd_isn is the offset
* of the first byte to send to the receiver. The difference is the number
* of bytes to be acknowledged.
/* The current acknowledgement number number is the (relative) offset
* of the of the next byte needed by the receiver. The snd_isn is the
* offset of the first byte to send to the receiver. The difference
* is the number of bytes to be acknowledged.
*/
pstate->snd_acked = send_getackno(dev) - pstate->snd_isn;
@ -175,23 +219,14 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
if ( pstate->snd_acked >= pstate->snd_buflen)
{
/* Yes. Then pstate->snd_len should hold the number of bytes actually
* sent.
*
* Don't allow any further call backs.
*/
conn->data_flags = 0;
conn->data_private = NULL;
conn->data_event = NULL;
/* Wake up the waiting thread, returning the number of bytes
/* Yes. Then pstate->snd_len should hold the number of bytes
* actually sent.
*/
sem_post(&pstate->snd_sem);
return flags;
goto end_wait;
}
/* No.. fall through to send more data if necessary */
}
/* Check if we are being asked to retransmit data */
@ -203,25 +238,19 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
*/
pstate->snd_sent = pstate->snd_acked;
/* Fall through to re-send data from the last that was ACKed */
}
/* Check for a loss of connection */
else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
/* Stop further callbacks */
conn->data_flags = 0;
conn->data_private = NULL;
conn->data_event = NULL;
/* Report not connected */
nvdbg("Lost connection\n");
pstate->snd_sent = -ENOTCONN;
/* Wake up the waiting thread */
sem_post(&pstate->snd_sem);
goto end_wait;
}
/* We get here if (1) not all of the data has been ACKed, (2) we have been
@ -250,6 +279,35 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
}
/* All data has been send and we are just waiting for ACK or re-tranmist
* indications to complete the send. Check for a timeout.
*/
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
else if (send_timeout(pstate))
{
/* Yes.. report the timeout */
nvdbg("TCP timeout\n");
pstate->snd_sent = -EAGAIN;
goto end_wait;
}
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
/* Continue waiting */
return flags;
end_wait:
/* Do not allow any further callbacks */
conn->data_flags = 0;
conn->data_private = NULL;
conn->data_event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->snd_sem);
return flags;
}