Index: CHANGELOG
===================================================================
RCS file: /sources/lwip/lwip/CHANGELOG,v
retrieving revision 1.124
diff -w -b -u -3 -p -B -r1.124 CHANGELOG
--- CHANGELOG	3 May 2007 19:13:27 -0000	1.124
+++ CHANGELOG	4 May 2007 13:32:53 -0000
@@ -23,6 +23,14 @@ HISTORY
 
   ++ New features:
 
+  2007-05-04 Frédéric Bernon, Jonathan Larmour
+  * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible
+    to corrupt remote addr/port connection state". Reduce problems "not enought memory" with
+    netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between
+    sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function.
+    Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct,
+    these fields are now renamed "addr" & "port".
+
   2007-04-11 Jonathan Larmour
   * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new
     sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return


Index: src/api/api_lib.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/api_lib.c,v
retrieving revision 1.35
diff -w -b -u -3 -p -B -r1.35 api_lib.c
--- src/api/api_lib.c	11 Apr 2007 15:41:04 -0000	1.35
+++ src/api/api_lib.c	4 May 2007 13:21:44 -0000
@@ -49,6 +49,7 @@ netbuf *netbuf_new(void)
   if (buf != NULL) {
     buf->p = NULL;
     buf->ptr = NULL;
+    buf->addr = NULL;
     return buf;
   } else {
     return NULL;
@@ -116,12 +117,6 @@ netbuf_chain(struct netbuf *head, struct
   memp_free(MEMP_NETBUF, tail);
 }
 
-u16_t
-netbuf_len(struct netbuf *buf)
-{
-  return buf->p->tot_len;
-}
-
 err_t
 netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
 {
@@ -184,24 +179,6 @@ netbuf_copy_partial(struct netbuf *buf, 
   }
 }
 
-void
-netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
-{
-  netbuf_copy_partial(buf, dataptr, len, 0);
-}
-
-struct ip_addr *
-netbuf_fromaddr(struct netbuf *buf)
-{
-  return buf->fromaddr;
-}
-
-u16_t
-netbuf_fromport(struct netbuf *buf)
-{
-  return buf->fromport;
-}
-
 struct
 netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
                                    void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
@@ -487,9 +462,11 @@ netconn_recv(struct netconn *conn)
   }
   
   if (conn->recvmbox == SYS_MBOX_NULL) {
+    if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
     conn->err = ERR_CONN;
     return NULL;
   }
+  }
 
   if (conn->err != ERR_OK) {
     return NULL;
@@ -533,8 +510,8 @@ netconn_recv(struct netconn *conn)
 
     buf->p = p;
     buf->ptr = p;
-    buf->fromport = 0;
-    buf->fromaddr = NULL;
+    buf->port = 0;
+    buf->addr = NULL;
 
     /* Let the stack know that we have taken the data. */
     msg.type = API_MSG_RECV;
@@ -565,6 +542,16 @@ netconn_recv(struct netconn *conn)
 }
 
 err_t
+netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port)
+{ if (buf!=NULL) {
+    buf->addr = addr;
+    buf->port = port;
+    return netconn_send( conn, buf);
+  }
+  return ERR_VAL;
+} 
+
+err_t
 netconn_send(struct netconn *conn, struct netbuf *buf)
 {
   struct api_msg msg;
@@ -580,7 +567,7 @@ netconn_send(struct netconn *conn, struc
   LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
   msg.type = API_MSG_SEND;
   msg.msg.conn = conn;
-  msg.msg.msg.p = buf->p;
+  msg.msg.msg.b = buf;
   api_msg_post(&msg);
   return conn->err;
 }


Index: src/api/api_msg.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/api_msg.c,v
retrieving revision 1.34
diff -w -b -u -3 -p -B -r1.34 api_msg.c
--- src/api/api_msg.c	5 Apr 2007 21:11:16 -0000	1.34
+++ src/api/api_msg.c	4 May 2007 13:22:29 -0000
@@ -57,8 +57,8 @@ recv_raw(void *arg, struct raw_pcb *pcb,
     pbuf_ref(p);
     buf->p = p;
     buf->ptr = p;
-    buf->fromaddr = addr;
-    buf->fromport = pcb->protocol;
+    buf->addr = addr;
+    buf->port = pcb->protocol;
 
     conn->recv_avail += p->tot_len;
     /* Register event with callback */
@@ -95,8 +95,8 @@ recv_udp(void *arg, struct udp_pcb *pcb,
     } else {
       buf->p = p;
       buf->ptr = p;
-      buf->fromaddr = addr;
-      buf->fromport = port;
+      buf->addr = addr;
+      buf->port = port;
     }
 
     conn->recv_avail += p->tot_len;
@@ -581,7 +581,11 @@ do_send(struct api_msg_msg *msg)
       switch (msg->conn->type) {
 #if LWIP_RAW
       case NETCONN_RAW:
-        raw_send(msg->conn->pcb.raw, msg->msg.p);
+        if (msg->msg.b->addr==NULL) {
+          raw_send(msg->conn->pcb.raw, msg->msg.b->p);
+        } else {
+          raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr);
+        }
         break;
 #endif
 #if LWIP_UDP
@@ -590,7 +594,11 @@ do_send(struct api_msg_msg *msg)
       case NETCONN_UDPNOCHKSUM:
         /* FALLTHROUGH */
       case NETCONN_UDP:

-        udp_send(msg->conn->pcb.udp, msg->msg.p);
+        if (msg->msg.b->addr==NULL) {
+          udp_send(msg->conn->pcb.udp, msg->msg.b->p);
+        } else {
+          udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port);
+        }
         break;
 #endif /* LWIP_UDP */
       case NETCONN_TCP:


Index: src/api/sockets.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/sockets.c,v
retrieving revision 1.43
diff -w -b -u -3 -p -B -r1.43 sockets.c
--- src/api/sockets.c	3 May 2007 19:13:27 -0000	1.43
+++ src/api/sockets.c	4 May 2007 13:19:58 -0000
@@ -461,7 +461,6 @@ int
 lwip_send(int s, const void *data, int size, unsigned int flags)
 {
   struct lwip_socket *sock;
-  struct netbuf *buf;
   err_t err;
 
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags));
@@ -470,45 +469,14 @@ lwip_send(int s, const void *data, int s
   if (!sock)
     return -1;
 
-  switch (netconn_type(sock->conn)) {
-  case NETCONN_RAW:
-  case NETCONN_UDP:
-  case NETCONN_UDPLITE:
-  case NETCONN_UDPNOCHKSUM:
-    /* create a buffer */
-    buf = netbuf_new();
-
-    if (!buf) {
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s));
-      sock_set_errno(sock, ENOBUFS);
-      return -1;
-    }
-
-    /* make the buffer point to the data that should be sent */
-    if ((err = netbuf_ref(buf, data, size))==ERR_OK) {
-      /* send the data */
-      err = netconn_send(sock->conn, buf);
-    }
+  if (sock->conn->type!=NETCONN_TCP)     
+    return lwip_sendto( s, data, size, flags, NULL, 0);
 
-    /* deallocated the buffer */
-    netbuf_delete(buf);
-    break;
-  case NETCONN_TCP:
     err = netconn_write(sock->conn, data, size, NETCONN_COPY);
-    break;
-  default:
-    err = ERR_ARG;
-    break;
-  }
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err));
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
 
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size));
-  sock_set_errno(sock, 0);
-  return size;
+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%d\n", s, err, size));
+  sock_set_errno(sock, err_to_errno(err));
+  return (err==ERR_OK?size:-1);
 }
 
 int
@@ -516,37 +484,51 @@ lwip_sendto(int s, const void *data, int
        struct sockaddr *to, socklen_t tolen)
 {
   struct lwip_socket *sock;
-  struct ip_addr remote_addr, addr;
-  u16_t remote_port, port;
-  int err,connected;
+  struct netbuf buf;
+  struct ip_addr remote_addr;
+  u16_t remote_port;
+  int err;
 
   sock = get_socket(s);
   if (!sock)
     return -1;
 
-  LWIP_ASSERT("lwip_sendto: invalid address", (tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET));
+  if (sock->conn->type==NETCONN_TCP)
+    return lwip_send( s, data, size, flags);
 
-  /* get the peer if currently connected */
-  connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);
+  LWIP_ASSERT("lwip_sendto: invalid address", (((to==NULL) && (tolen==0)) || ((tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET))) );
 
+  /* initialize a buffer */
+  buf.p = buf.ptr = NULL;
+  if (to) {
   remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
-  remote_port = ((struct sockaddr_in *)to)->sin_port;
+    remote_port      = ntohs(((struct sockaddr_in *)to)->sin_port);
+    buf.addr         = &remote_addr;
+    buf.port         = remote_port;
+  } else {
+    remote_addr.addr = 0;
+    remote_port      = 0;
+    buf.addr         = NULL;
+    buf.port         = 0;
+  }
 
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
   ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
+  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", remote_port));
 
-  netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
+  /* make the buffer point to the data that should be sent */
+  if ((err = netbuf_ref(&buf, data, size))==ERR_OK) {
+    /* send the data */
+    err = netconn_send(sock->conn, &buf);
+  }
 
-  err = lwip_send(s, data, size, flags);
+  /* deallocated the buffer */
+  if (buf.p != NULL) {
+    pbuf_free(buf.p);
+  }
 
-  /* reset the remote address and port number
-     of the connection */
-  if (connected)
-    netconn_connect(sock->conn, &addr, port);
-  else
-    netconn_disconnect(sock->conn);
-  return err;
+  sock_set_errno(sock, err_to_errno(err));
+  return (err==ERR_OK?size:-1);
 }
 
 int


Index: src/include/lwip/api.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/api.h,v
retrieving revision 1.14
diff -w -b -u -3 -p -B -r1.14 api.h
--- src/include/lwip/api.h	28 Mar 2007 17:26:06 -0000	1.14
+++ src/include/lwip/api.h	4 May 2007 13:18:49 -0000
@@ -80,8 +80,8 @@ enum netconn_igmp {
 
 struct netbuf {
   struct pbuf *p, *ptr;
-  struct ip_addr *fromaddr;
-  u16_t fromport;
+  struct ip_addr *addr;
+  u16_t port;
 };
 
 struct netconn {
@@ -121,12 +121,13 @@ err_t             netbuf_data     (struc
 s8_t              netbuf_next     (struct netbuf *buf);
 void              netbuf_first    (struct netbuf *buf);
 
-void              netbuf_copy     (struct netbuf *buf,
-           void *dataptr, u16_t len);
 void              netbuf_copy_partial(struct netbuf *buf, void *dataptr, 
               u16_t len, u16_t offset);
-struct ip_addr *  netbuf_fromaddr (struct netbuf *buf);
-u16_t             netbuf_fromport (struct netbuf *buf);
+
+#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)              
+#define netbuf_len(buf)              ((buf)->p->tot_len)
+#define netbuf_fromaddr(buf)         ((buf)->addr)
+#define netbuf_fromport(buf)         ((buf)->port)
 
 /* Network connection functions: */
 struct netconn *  netconn_new     (enum netconn_type type);
@@ -154,6 +155,8 @@ err_t             netconn_disconnect (st
 err_t             netconn_listen  (struct netconn *conn);
 struct netconn *  netconn_accept  (struct netconn *conn);
 struct netbuf *   netconn_recv    (struct netconn *conn);
+err_t             netconn_sendto  (struct netconn *conn,
+           struct netbuf *buf, struct ip_addr *addr, u16_t port);
 err_t             netconn_send    (struct netconn *conn,
            struct netbuf *buf);
 err_t             netconn_write   (struct netconn *conn,


Index: src/include/lwip/api_msg.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/api_msg.h,v
retrieving revision 1.9
diff -w -b -u -3 -p -B -r1.9 api_msg.h
--- src/include/lwip/api_msg.h	22 Mar 2007 09:34:18 -0000	1.9
+++ src/include/lwip/api_msg.h	3 May 2007 18:22:08 -0000
@@ -71,6 +71,7 @@ struct api_msg_msg {
   enum netconn_type conntype;
   union {
     struct pbuf *p;   
+    struct netbuf *b;
     struct  {
       struct ip_addr *ipaddr;
       u16_t port;
