Implement UDP sendto() timeouts. Currently disabled because it probably unnecessary.

This commit is contained in:
Gregory Nutt 2013-04-30 08:12:54 -06:00
parent fad8a2b555
commit c9d98ea46c
3 changed files with 114 additions and 24 deletions

View File

@ -4639,5 +4639,7 @@
6.28 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
* arch/arm/src/lpc17xx/lpc17_i2c.c: Interrupts were not being
re-enabled in the I2C intializatin function.
re-enabled in the I2C intializatin function (2013-4-30).
* net/sendto.c: Added skeleton of implementation of send timeouts
for UDP. However, this functionality really does not make
sense, so it is disabled in the code (2013-4-30).

View File

@ -89,7 +89,7 @@ struct send_s
uint32_t snd_isn; /* Initial sequence number */
uint32_t snd_acked; /* The number of bytes acked */
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
uint32_t snd_time; /* last send time for determining timeout */
uint32_t snd_time; /* Last send time for determining timeout */
#endif
#if defined(CONFIG_NET_TCP_SPLIT)
bool snd_odd; /* True: Odd packet in pair transaction */
@ -118,7 +118,7 @@ struct send_s
****************************************************************************/
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
static inline int send_timeout(struct send_s *pstate)
static inline int send_timeout(FAR struct send_s *pstate)
{
FAR struct socket *psock = 0;
@ -160,11 +160,11 @@ static inline int send_timeout(struct send_s *pstate)
*
****************************************************************************/
static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
void *pvpriv, uint16_t flags)
static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
struct uip_conn *conn = (struct uip_conn*)pvconn;
struct send_s *pstate = (struct send_s *)pvpriv;
FAR struct uip_conn *conn = (FAR struct uip_conn*)pvconn;
FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
nllvdbg("flags: %04x acked: %d sent: %d\n",
flags, pstate->snd_acked, pstate->snd_sent);
@ -501,7 +501,8 @@ end_wait:
*
****************************************************************************/
ssize_t psock_send(FAR struct socket *psock, const void *buf, size_t len, int flags)
ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
int flags)
{
struct send_s state;
uip_lock_t save;
@ -561,7 +562,7 @@ ssize_t psock_send(FAR struct socket *psock, const void *buf, size_t len, int fl
conn->unacked = 0;
/* Update the initial time for calculating timeouts */
/* Set the initial time for calculating timeouts */
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
state.snd_time = clock_systimer();
@ -622,7 +623,7 @@ ssize_t psock_send(FAR struct socket *psock, const void *buf, size_t len, int fl
return state.snd_sent;
errout:
*get_errno_ptr() = err;
set_errno(err);
return ERROR;
}
@ -690,7 +691,7 @@ errout:
*
****************************************************************************/
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags)
{
return psock_send(sockfd_socket(sockfd), buf, len, flags);
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* net/sendto.c
*
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -47,14 +47,35 @@
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <nuttx/clock.h>
#include <nuttx/net/uip/uip-arch.h>
#include "net_internal.h"
#include "uip/uip_internal.h"
/****************************************************************************
* Definitions
* Pre-processor Definitions
****************************************************************************/
/* timeouts on sendto() do not make sense. Each polling cycle from the
* driver is an opportunity to send a packet. If the driver is not polling,
* then the network is not up (and there is not polling cycles to drive
* the timeout).
*
* There is a remote possibility that if there is a lot of other network
* traffic that a UDP sendto could get delayed, but I would not expect this
* generate a timeout.
*/
#undef CONFIG_NET_SENDTO_TIMEOUT
/* If supported, the sendto timeout function would depend on socket options
* and a system clock.
*/
#if !defined(CONFIG_NET_SOCKOPTS) || defined(CONFIG_DISABLE_CLOCK)
# undef CONFIG_NET_SENDTO_TIMEOUT
#endif
/****************************************************************************
* Private Types
@ -62,17 +83,61 @@
struct sendto_s
{
#ifdef CONFIG_NET_SENDTO_TIMEOUT
FAR struct socket *st_sock; /* Points to the parent socket structure */
uint32_t st_time; /* Last send time for determining timeout */
#endif
FAR struct uip_callback_s *st_cb; /* Reference to callback instance */
sem_t st_sem; /* Semaphore signals sendto completion */
uint16_t st_buflen; /* Length of send buffer (error if <0) */
const char *st_buffer; /* Pointer to send buffer */
int st_sndlen; /* Result of the send (length sent or negated errno) */
sem_t st_sem; /* Semaphore signals sendto completion */
uint16_t st_buflen; /* Length of send buffer (error if <0) */
const char *st_buffer; /* Pointer to send buffer */
int st_sndlen; /* Result of the send (length sent or negated errno) */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* 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
*
****************************************************************************/
#ifdef CONFIG_NET_SENDTO_TIMEOUT
static inline int send_timeout(FAR struct sendto_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->st_sock;
if (psock && psock->s_sndtimeo != 0)
{
/* Check if the configured timeout has elapsed */
return net_timeo(pstate->st_time, psock->s_sndtimeo);
}
/* No timeout */
return FALSE;
}
#endif /* CONFIG_NET_SENDTO_TIMEOUT */
/****************************************************************************
* Function: sendto_interrupt
*
@ -98,12 +163,12 @@ struct sendto_s
static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
void *pvpriv, uint16_t flags)
{
struct sendto_s *pstate = (struct sendto_s *)pvpriv;
FAR struct sendto_s *pstate = (FAR struct sendto_s *)pvpriv;
nllvdbg("flags: %04x\n", flags);
if (pstate)
{
/* Check if the outgoing packet is available (it may have been claimed
/* Check if the outgoing packet is available. It may have been claimed
* by a sendto interrupt serving a different thread -OR- if the output
* buffer currently contains unprocessed incoming data. In these cases
* we will just have to wait for the next polling cycle.
@ -112,10 +177,25 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
if (dev->d_sndlen > 0 || (flags & UIP_NEWDATA) != 0)
{
/* Another thread has beat us sending data or the buffer is busy,
* wait for the next polling cycle
* Check for a timeout. If not timed out, wait for the next
* polling cycle and check again.
*/
return flags;
#ifdef CONFIG_NET_SENDTO_TIMEOUT
if (send_timeout(pstate))
{
/* Yes.. report the timeout */
nlldbg("SEND timeout\n");
pstate->st_sndlen = -ETIMEDOUT;
}
else
#endif /* CONFIG_NET_SENDTO_TIMEOUT */
{
/* No timeout. Just wait for the next polling cycle */
return flags;
}
}
/* It looks like we are good to send the data */
@ -283,12 +363,19 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
* are ready.
*/
save = uip_lock();
save = uip_lock();
memset(&state, 0, sizeof(struct sendto_s));
sem_init(&state.st_sem, 0, 0);
state.st_buflen = len;
state.st_buffer = buf;
/* Set the initial time for calculating timeouts */
#ifdef CONFIG_NET_SENDTO_TIMEOUT
state.st_sock = psock;
state.st_time = clock_systimer();
#endif
/* Setup the UDP socket */
conn = (struct uip_udp_conn *)psock->s_conn;
@ -354,7 +441,7 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
#endif
errout:
errno = err;
set_errno(err);
return ERROR;
}