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:
parent
929a52b3e0
commit
4c54d7d07e
5 changed files with 92 additions and 38 deletions
|
@ -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
|
||||
|
|
|
@ -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
7
TODO
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
114
net/send.c
114
net/send.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue