lwip-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-devel] [patch #5780] Implement SO_RCVTIMEO on UDP sockets/netconn


From: Frédéric Bernon
Subject: [lwip-devel] [patch #5780] Implement SO_RCVTIMEO on UDP sockets/netconn
Date: Sun, 04 Mar 2007 13:56:12 +0000
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1.2) Gecko/20070219 Firefox/2.0.0.2

URL:
  <http://savannah.nongnu.org/patch/?5780>

                 Summary: Implement SO_RCVTIMEO on UDP sockets/netconn
                 Project: lwIP - A Lightweight TCP/IP stack
            Submitted by: fbernon
            Submitted on: dimanche 04.03.2007 à 14:56
                Category: None
                Priority: 5 - Normal
                  Status: In Progress
                 Privacy: Public
             Assigned to: fbernon
        Originator Email: 
             Open/Closed: Open
         Discussion Lock: Any

    _______________________________________________________

Details:

I propose to add the possibility to use the socket's option name SO_RCVTIMEO
on UDP sockets. It's very usefull in some UDP protocols, like SNTP or DNS,
where you have to wait an answer which can never arrived (packet lost, server
shutdown...). SO_RCVTIMEO is a very generic parameter. It allow to give a code
very simple (you can do something like that with select, but it's not the
simplest solution).


The patch is very simple, and need to add a "timeout" parameter in
sys_mbox_fetch (in sys.h/.c):

void sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout);

In the sys.c implementation, the only thing to do is the give this new
parameter to sys_arch_mbox_fetch.

Most of calling functions have to set it to 0, but in netconn_recv, we can
pass the different values, initialize with SO_RCVTIMEO, and register in a
netconn member.

To handle the timeout, in netconn_recv (see below), we just return a NULL
value, like this :

struct netbuf *
netconn_recv(struct netconn *conn)
{
  struct api_msg _msg;
  struct api_msg *msg = &_msg;
  struct netbuf *buf = NULL;
  struct pbuf *p;
  u16_t len;
      
  if (conn == NULL) {
    return NULL;
  }
 
  if (conn->recvmbox == SYS_MBOX_NULL) {
    conn->err = ERR_CONN;
    return NULL;
  }

  if (conn->err != ERR_OK) {
    return NULL;
  }

  if (conn->type == NETCONN_TCP) {
    if (conn->pcb.tcp->state == LISTEN) {
      conn->err = ERR_CONN;
      return NULL;
    }


    buf = memp_malloc(MEMP_NETBUF);

    if (buf == NULL) {
      conn->err = ERR_MEM;
      return NULL;
    }
    
    sys_mbox_fetch(conn->recvmbox, (void *)&p, 0);

    if (p != NULL)
    {
        len = p->tot_len;
        conn->recv_avail -= len;
    }
    else
        len = 0;
    
    /* Register event with callback */
      if (conn->callback)
        (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);

    /* If we are closed, we indicate that we no longer wish to receive
       data by setting conn->recvmbox to SYS_MBOX_NULL. */
    if (p == NULL) {
      memp_free(MEMP_NETBUF, buf);
      sys_mbox_free(conn->recvmbox);
      conn->recvmbox = SYS_MBOX_NULL;
      return NULL;
    }

    buf->p = p;
    buf->ptr = p;
    buf->fromport = 0;
    buf->fromaddr = NULL;

    /* Let the stack know that we have taken the data. */
    msg->type = API_MSG_RECV;
    msg->msg.conn = conn;
    if (buf != NULL) {
      msg->msg.msg.len = buf->p->tot_len;
    } else {
      msg->msg.msg.len = 1;
    }
    api_msg_post(msg);

    sys_mbox_fetch(conn->mbox, NULL, 0);
  } else {
    sys_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout);
    if (buf!=NULL)
     { conn->recv_avail -= buf->p->tot_len;
       /* Register event with callback */
       if (conn->callback)
           (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
     }
  }

  

    
  LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void
*)buf, conn->err));


  return buf;
}

In sockets.c, we change only in lwip_recvfrom (ETIMEDOUT is this new error
code):

     //...
     /* No data was left from the previous operation, so we try to get
     some from the network. */
     buf = netconn_recv(sock->conn);
     
     if (!buf) {
        /* We should really do some error checking here. */
        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
       
        sock_set_errno(sock, (sock->conn->type==NETCONN_UDP)?ETIMEDOUT:0);
        return 0;
      }
     //...


Is it good for you?






    _______________________________________________________

Reply to this item at:

  <http://savannah.nongnu.org/patch/?5780>

_______________________________________________
  Message posté via/par Savannah
  http://savannah.nongnu.org/





reply via email to

[Prev in Thread] Current Thread [Next in Thread]