Update to V4.3.0 as described in http://www.FreeRTOS.org/History.txt

diff --git a/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_lib.c b/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_lib.c
index 3d83d1e..d9cf7ef 100644
--- a/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_lib.c
+++ b/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_lib.c
@@ -1,729 +1,729 @@
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-/* This is the part of the API that is linked with
-   the application */
-
-#include "lwip/opt.h"
-#include "lwip/api.h"
-#include "lwip/api_msg.h"
-#include "lwip/memp.h"
-
-
-struct
-netbuf *netbuf_new(void)
-{
-  struct netbuf *buf;
-
-  buf = memp_malloc(MEMP_NETBUF);
-  if (buf != NULL) {
-    buf->p = NULL;
-    buf->ptr = NULL;
-    return buf;
-  } else {
-    return NULL;
-  }
-}
-
-void
-netbuf_delete(struct netbuf *buf)
-{
-  if (buf != NULL) {
-    if (buf->p != NULL) {
-      pbuf_free(buf->p);
-      buf->p = buf->ptr = NULL;
-    }
-    memp_free(MEMP_NETBUF, buf);
-  }
-}
-
-void *
-netbuf_alloc(struct netbuf *buf, u16_t size)
-{
-  /* Deallocate any previously allocated memory. */
-  if (buf->p != NULL) {
-    pbuf_free(buf->p);
-  }
-  buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
-  if (buf->p == NULL) {
-     return NULL;
-  }
-  buf->ptr = buf->p;
-  return buf->p->payload;
-}
-
-void
-netbuf_free(struct netbuf *buf)
-{
-  if (buf->p != NULL) {
-    pbuf_free(buf->p);
-  }
-  buf->p = buf->ptr = NULL;
-}
-
-void
-netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
-{
-  if (buf->p != NULL) {
-    pbuf_free(buf->p);
-  }
-  buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
-  buf->p->payload = dataptr;
-  buf->p->len = buf->p->tot_len = size;
-  buf->ptr = buf->p;
-}
-
-void
-netbuf_chain(struct netbuf *head, struct netbuf *tail)
-{
-  pbuf_chain(head->p, tail->p);
-  head->ptr = head->p;
-  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)
-{
-  if (buf->ptr == NULL) {
-    return ERR_BUF;
-  }
-  *dataptr = buf->ptr->payload;
-  *len = buf->ptr->len;
-  return ERR_OK;
-}
-
-s8_t
-netbuf_next(struct netbuf *buf)
-{
-  if (buf->ptr->next == NULL) {
-    return -1;
-  }
-  buf->ptr = buf->ptr->next;
-  if (buf->ptr->next == NULL) {
-    return 1;
-  }
-  return 0;
-}
-
-void
-netbuf_first(struct netbuf *buf)
-{
-  buf->ptr = buf->p;
-}
-
-void
-netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
-{
-  struct pbuf *p;
-  u16_t i, left;
-
-  left = 0;
-
-  if(buf == NULL || dataptr == NULL) {
-    return;
-  }
-  
-  /* This implementation is bad. It should use bcopy
-     instead. */
-  for(p = buf->p; left < len && p != NULL; p = p->next) {
-    if (offset != 0 && offset >= p->len) {
-      offset -= p->len;
-    } else {    
-      for(i = offset; i < p->len; ++i) {
-  ((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];
-  if (++left >= len) {
-    return;
-  }
-      }
-      offset = 0;
-    }
-  }
-}
-
-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))
-{
-  struct netconn *conn;
-  struct api_msg *msg;
-
-  conn = memp_malloc(MEMP_NETCONN);
-  if (conn == NULL) {
-    return NULL;
-  }
-  
-  conn->err = ERR_OK;
-  conn->type = t;
-  conn->pcb.tcp = NULL;
-
-  if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
-    memp_free(MEMP_NETCONN, conn);
-    return NULL;
-  }
-  conn->recvmbox = SYS_MBOX_NULL;
-  conn->acceptmbox = SYS_MBOX_NULL;
-  conn->sem = SYS_SEM_NULL;
-  conn->state = NETCONN_NONE;
-  conn->socket = 0;
-  conn->callback = callback;
-  conn->recv_avail = 0;
-
-  if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    memp_free(MEMP_NETCONN, conn);
-    return NULL;
-  }
-  
-  msg->type = API_MSG_NEWCONN;
-  msg->msg.msg.bc.port = proto; /* misusing the port field */
-  msg->msg.conn = conn;
-  api_msg_post(msg);  
-  sys_mbox_fetch(conn->mbox, NULL);
-  memp_free(MEMP_API_MSG, msg);
-
-  if ( conn->err != ERR_OK ) {
-    memp_free(MEMP_NETCONN, conn);
-    return NULL;
-  }
-
-  return conn;
-}
-
-
-struct
-netconn *netconn_new(enum netconn_type t)
-{
-  return netconn_new_with_proto_and_callback(t,0,NULL);
-}
-
-struct
-netconn *netconn_new_with_callback(enum netconn_type t,
-                                   void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
-{
-  return netconn_new_with_proto_and_callback(t,0,callback);
-}
-
-
-err_t
-netconn_delete(struct netconn *conn)
-{
-  struct api_msg *msg;
-  void *mem;
-  
-  if (conn == NULL) {
-    return ERR_OK;
-  }
-  
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return ERR_MEM;
-  }
-  
-  msg->type = API_MSG_DELCONN;
-  msg->msg.conn = conn;
-  api_msg_post(msg);  
-  sys_mbox_fetch(conn->mbox, NULL);
-  memp_free(MEMP_API_MSG, msg);
-
-  /* Drain the recvmbox. */
-  if (conn->recvmbox != SYS_MBOX_NULL) {
-    while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
-      if (conn->type == NETCONN_TCP) {
-        if(mem != NULL)
-          pbuf_free((struct pbuf *)mem);
-      } else {
-        netbuf_delete((struct netbuf *)mem);
-      }
-    }
-    sys_mbox_free(conn->recvmbox);
-    conn->recvmbox = SYS_MBOX_NULL;
-  }
- 
-
-  /* Drain the acceptmbox. */
-  if (conn->acceptmbox != SYS_MBOX_NULL) {
-    while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
-      netconn_delete((struct netconn *)mem);
-    }
-    
-    sys_mbox_free(conn->acceptmbox);
-    conn->acceptmbox = SYS_MBOX_NULL;
-  }
-
-  sys_mbox_free(conn->mbox);
-  conn->mbox = SYS_MBOX_NULL;
-  if (conn->sem != SYS_SEM_NULL) {
-    sys_sem_free(conn->sem);
-  }
-  /*  conn->sem = SYS_SEM_NULL;*/
-  memp_free(MEMP_NETCONN, conn);
-  return ERR_OK;
-}
-
-enum netconn_type
-netconn_type(struct netconn *conn)
-{
-  return conn->type;
-}
-
-err_t
-netconn_peer(struct netconn *conn, struct ip_addr *addr,
-       u16_t *port)
-{
-  switch (conn->type) {
-  case NETCONN_RAW:
-    /* return an error as connecting is only a helper for upper layers */
-    return ERR_CONN;
-  case NETCONN_UDPLITE:
-  case NETCONN_UDPNOCHKSUM:
-  case NETCONN_UDP:
-    if (conn->pcb.udp == NULL ||
-  ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
-     return ERR_CONN;
-    *addr = (conn->pcb.udp->remote_ip);
-    *port = conn->pcb.udp->remote_port;
-    break;
-  case NETCONN_TCP:
-    if (conn->pcb.tcp == NULL)
-      return ERR_CONN;
-    *addr = (conn->pcb.tcp->remote_ip);
-    *port = conn->pcb.tcp->remote_port;
-    break;
-  }
-  return (conn->err = ERR_OK);
-}
-
-err_t
-netconn_addr(struct netconn *conn, struct ip_addr **addr,
-       u16_t *port)
-{
-  switch (conn->type) {
-  case NETCONN_RAW:
-    *addr = &(conn->pcb.raw->local_ip);
-    *port = conn->pcb.raw->protocol;
-    break;
-  case NETCONN_UDPLITE:
-  case NETCONN_UDPNOCHKSUM:
-  case NETCONN_UDP:
-    *addr = &(conn->pcb.udp->local_ip);
-    *port = conn->pcb.udp->local_port;
-    break;
-  case NETCONN_TCP:
-    *addr = &(conn->pcb.tcp->local_ip);
-    *port = conn->pcb.tcp->local_port;
-    break;
-  }
-  return (conn->err = ERR_OK);
-}
-
-err_t
-netconn_bind(struct netconn *conn, struct ip_addr *addr,
-      u16_t port)
-{
-  struct api_msg *msg;
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-
-  if (conn->type != NETCONN_TCP &&
-     conn->recvmbox == SYS_MBOX_NULL) {
-    if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
-      return ERR_MEM;
-    }
-  }
-  
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return (conn->err = ERR_MEM);
-  }
-  msg->type = API_MSG_BIND;
-  msg->msg.conn = conn;
-  msg->msg.msg.bc.ipaddr = addr;
-  msg->msg.msg.bc.port = port;
-  api_msg_post(msg);
-  sys_mbox_fetch(conn->mbox, NULL);
-  memp_free(MEMP_API_MSG, msg);
-  return conn->err;
-}
-
-
-err_t
-netconn_connect(struct netconn *conn, struct ip_addr *addr,
-       u16_t port)
-{
-  struct api_msg *msg;
-  
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-
-
-  if (conn->recvmbox == SYS_MBOX_NULL) {
-    if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
-      return ERR_MEM;
-    }
-  }
-  
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return ERR_MEM;
-  }
-  msg->type = API_MSG_CONNECT;
-  msg->msg.conn = conn;  
-  msg->msg.msg.bc.ipaddr = addr;
-  msg->msg.msg.bc.port = port;
-  api_msg_post(msg);
-  sys_mbox_fetch(conn->mbox, NULL);
-  memp_free(MEMP_API_MSG, msg);
-  return conn->err;
-}
-
-err_t
-netconn_disconnect(struct netconn *conn)
-{
-  struct api_msg *msg;
-  
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return ERR_MEM;
-  }
-  msg->type = API_MSG_DISCONNECT;
-  msg->msg.conn = conn;  
-  api_msg_post(msg);
-  sys_mbox_fetch(conn->mbox, NULL);
-  memp_free(MEMP_API_MSG, msg);
-  return conn->err;
-
-}
-
-err_t
-netconn_listen(struct netconn *conn)
-{
-  struct api_msg *msg;
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-
-  if (conn->acceptmbox == SYS_MBOX_NULL) {
-    conn->acceptmbox = sys_mbox_new();
-    if (conn->acceptmbox == SYS_MBOX_NULL) {
-      return ERR_MEM;
-    }
-  }
-  
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return (conn->err = ERR_MEM);
-  }
-  msg->type = API_MSG_LISTEN;
-  msg->msg.conn = conn;
-  api_msg_post(msg);
-  sys_mbox_fetch(conn->mbox, NULL);
-  memp_free(MEMP_API_MSG, msg);
-  return conn->err;
-}
-
-struct netconn *
-netconn_accept(struct netconn *conn)
-{
-  struct netconn *newconn;
-  
-  if (conn == NULL) {
-    return NULL;
-  }
-  
-  sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
-  /* Register event with callback */
-  if (conn->callback)
-      (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
-  
-  return newconn;
-}
-
-struct netbuf *
-netconn_recv(struct netconn *conn)
-{
-  struct api_msg *msg;
-  struct netbuf *buf;
-  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);
-
-    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. */
-    if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-      conn->err = ERR_MEM;
-      return buf;
-    }
-    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);
-    memp_free(MEMP_API_MSG, msg);
-  } else {
-    sys_mbox_fetch(conn->recvmbox, (void **)&buf);
-  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;
-}
-
-err_t
-netconn_send(struct netconn *conn, struct netbuf *buf)
-{
-  struct api_msg *msg;
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-
-  if (conn->err != ERR_OK) {
-    return conn->err;
-  }
-
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return (conn->err = ERR_MEM);
-  }
-
-  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;
-  api_msg_post(msg);
-
-  sys_mbox_fetch(conn->mbox, NULL);
-  memp_free(MEMP_API_MSG, msg);
-  return conn->err;
-}
-
-err_t
-netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
-{
-  struct api_msg *msg;
-  u16_t len;
-  
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-
-  if (conn->err != ERR_OK) {
-    return conn->err;
-  }
-  
-  if (conn->sem == SYS_SEM_NULL) {
-    conn->sem = sys_sem_new(0);
-    if (conn->sem == SYS_SEM_NULL) {
-      return ERR_MEM;
-    }
-  }
-
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return (conn->err = ERR_MEM);
-  }
-  msg->type = API_MSG_WRITE;
-  msg->msg.conn = conn;
-        
-
-  conn->state = NETCONN_WRITE;
-  while (conn->err == ERR_OK && size > 0) {
-    msg->msg.msg.w.dataptr = dataptr;
-    msg->msg.msg.w.copy = copy;
-    
-    if (conn->type == NETCONN_TCP) {
-      if (tcp_sndbuf(conn->pcb.tcp) == 0) {
-  sys_sem_wait(conn->sem);
-  if (conn->err != ERR_OK) {
-    goto ret;
-  }
-      }
-      if (size > tcp_sndbuf(conn->pcb.tcp)) {
-  /* We cannot send more than one send buffer's worth of data at a
-     time. */
-  len = tcp_sndbuf(conn->pcb.tcp);
-      } else {
-  len = size;
-      }
-    } else {
-      len = size;
-    }
-    
-    LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
-    msg->msg.msg.w.len = len;
-    api_msg_post(msg);
-    sys_mbox_fetch(conn->mbox, NULL);    
-    if (conn->err == ERR_OK) {
-      dataptr = (void *)((u8_t *)dataptr + len);
-      size -= len;
-    } else if (conn->err == ERR_MEM) {
-      conn->err = ERR_OK;
-      sys_sem_wait(conn->sem);
-    } else {
-      goto ret;
-    }
-  }
- ret:
-  memp_free(MEMP_API_MSG, msg);
-  conn->state = NETCONN_NONE;
-  if (conn->sem != SYS_SEM_NULL) {
-    sys_sem_free(conn->sem);
-    conn->sem = SYS_SEM_NULL;
-  }
-  
-  return conn->err;
-}
-
-err_t
-netconn_close(struct netconn *conn)
-{
-  struct api_msg *msg;
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
-    return (conn->err = ERR_MEM);
-  }
-
-  conn->state = NETCONN_CLOSE;
- again:
-  msg->type = API_MSG_CLOSE;
-  msg->msg.conn = conn;
-  api_msg_post(msg);
-  sys_mbox_fetch(conn->mbox, NULL);
-  if (conn->err == ERR_MEM &&
-     conn->sem != SYS_SEM_NULL) {
-    sys_sem_wait(conn->sem);
-    goto again;
-  }
-  conn->state = NETCONN_NONE;
-  memp_free(MEMP_API_MSG, msg);
-  return conn->err;
-}
-
-err_t
-netconn_err(struct netconn *conn)
-{
-  return conn->err;
-}
-
+/*

+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.

+ * All rights reserved. 

+ * 

+ * Redistribution and use in source and binary forms, with or without modification, 

+ * are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice,

+ *    this list of conditions and the following disclaimer.

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ * 3. The name of the author may not be used to endorse or promote products

+ *    derived from this software without specific prior written permission. 

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 

+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 

+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 

+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 

+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 

+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 

+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 

+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 

+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 

+ * OF SUCH DAMAGE.

+ *

+ * This file is part of the lwIP TCP/IP stack.

+ * 

+ * Author: Adam Dunkels <adam@sics.se>

+ *

+ */

+

+/* This is the part of the API that is linked with

+   the application */

+

+#include "lwip/opt.h"

+#include "lwip/api.h"

+#include "lwip/api_msg.h"

+#include "lwip/memp.h"

+

+

+struct

+netbuf *netbuf_new(void)

+{

+  struct netbuf *buf;

+

+  buf = memp_malloc(MEMP_NETBUF);

+  if (buf != NULL) {

+    buf->p = NULL;

+    buf->ptr = NULL;

+    return buf;

+  } else {

+    return NULL;

+  }

+}

+

+void

+netbuf_delete(struct netbuf *buf)

+{

+  if (buf != NULL) {

+    if (buf->p != NULL) {

+      pbuf_free(buf->p);

+      buf->p = buf->ptr = NULL;

+    }

+    memp_free(MEMP_NETBUF, buf);

+  }

+}

+

+void *

+netbuf_alloc(struct netbuf *buf, u16_t size)

+{

+  /* Deallocate any previously allocated memory. */

+  if (buf->p != NULL) {

+    pbuf_free(buf->p);

+  }

+  buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);

+  if (buf->p == NULL) {

+     return NULL;

+  }

+  buf->ptr = buf->p;

+  return buf->p->payload;

+}

+

+void

+netbuf_free(struct netbuf *buf)

+{

+  if (buf->p != NULL) {

+    pbuf_free(buf->p);

+  }

+  buf->p = buf->ptr = NULL;

+}

+

+void

+netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)

+{

+  if (buf->p != NULL) {

+    pbuf_free(buf->p);

+  }

+  buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);

+  buf->p->payload = dataptr;

+  buf->p->len = buf->p->tot_len = size;

+  buf->ptr = buf->p;

+}

+

+void

+netbuf_chain(struct netbuf *head, struct netbuf *tail)

+{

+  pbuf_chain(head->p, tail->p);

+  head->ptr = head->p;

+  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)

+{

+  if (buf->ptr == NULL) {

+    return ERR_BUF;

+  }

+  *dataptr = buf->ptr->payload;

+  *len = buf->ptr->len;

+  return ERR_OK;

+}

+

+s8_t

+netbuf_next(struct netbuf *buf)

+{

+  if (buf->ptr->next == NULL) {

+    return -1;

+  }

+  buf->ptr = buf->ptr->next;

+  if (buf->ptr->next == NULL) {

+    return 1;

+  }

+  return 0;

+}

+

+void

+netbuf_first(struct netbuf *buf)

+{

+  buf->ptr = buf->p;

+}

+

+void

+netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)

+{

+  struct pbuf *p;

+  u16_t i, left;

+

+  left = 0;

+

+  if(buf == NULL || dataptr == NULL) {

+    return;

+  }

+  

+  /* This implementation is bad. It should use bcopy

+     instead. */

+  for(p = buf->p; left < len && p != NULL; p = p->next) {

+    if (offset != 0 && offset >= p->len) {

+      offset -= p->len;

+    } else {    

+      for(i = offset; i < p->len; ++i) {

+  ((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];

+  if (++left >= len) {

+    return;

+  }

+      }

+      offset = 0;

+    }

+  }

+}

+

+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))

+{

+  struct netconn *conn;

+  struct api_msg *msg;

+

+  conn = memp_malloc(MEMP_NETCONN);

+  if (conn == NULL) {

+    return NULL;

+  }

+  

+  conn->err = ERR_OK;

+  conn->type = t;

+  conn->pcb.tcp = NULL;

+

+  if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {

+    memp_free(MEMP_NETCONN, conn);

+    return NULL;

+  }

+  conn->recvmbox = SYS_MBOX_NULL;

+  conn->acceptmbox = SYS_MBOX_NULL;

+  conn->sem = SYS_SEM_NULL;

+  conn->state = NETCONN_NONE;

+  conn->socket = 0;

+  conn->callback = callback;

+  conn->recv_avail = 0;

+

+  if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    memp_free(MEMP_NETCONN, conn);

+    return NULL;

+  }

+  

+  msg->type = API_MSG_NEWCONN;

+  msg->msg.msg.bc.port = proto; /* misusing the port field */

+  msg->msg.conn = conn;

+  api_msg_post(msg);  

+  sys_mbox_fetch(conn->mbox, NULL);

+  memp_free(MEMP_API_MSG, msg);

+

+  if ( conn->err != ERR_OK ) {

+    memp_free(MEMP_NETCONN, conn);

+    return NULL;

+  }

+

+  return conn;

+}

+

+

+struct

+netconn *netconn_new(enum netconn_type t)

+{

+  return netconn_new_with_proto_and_callback(t,0,NULL);

+}

+

+struct

+netconn *netconn_new_with_callback(enum netconn_type t,

+                                   void (*callback)(struct netconn *, enum netconn_evt, u16_t len))

+{

+  return netconn_new_with_proto_and_callback(t,0,callback);

+}

+

+

+err_t

+netconn_delete(struct netconn *conn)

+{

+  struct api_msg *msg;

+  void *mem;

+  

+  if (conn == NULL) {

+    return ERR_OK;

+  }

+  

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return ERR_MEM;

+  }

+  

+  msg->type = API_MSG_DELCONN;

+  msg->msg.conn = conn;

+  api_msg_post(msg);  

+  sys_mbox_fetch(conn->mbox, NULL);

+  memp_free(MEMP_API_MSG, msg);

+

+  /* Drain the recvmbox. */

+  if (conn->recvmbox != SYS_MBOX_NULL) {

+    while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {

+      if (conn->type == NETCONN_TCP) {

+        if(mem != NULL)

+          pbuf_free((struct pbuf *)mem);

+      } else {

+        netbuf_delete((struct netbuf *)mem);

+      }

+    }

+    sys_mbox_free(conn->recvmbox);

+    conn->recvmbox = SYS_MBOX_NULL;

+  }

+ 

+

+  /* Drain the acceptmbox. */

+  if (conn->acceptmbox != SYS_MBOX_NULL) {

+    while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {

+      netconn_delete((struct netconn *)mem);

+    }

+    

+    sys_mbox_free(conn->acceptmbox);

+    conn->acceptmbox = SYS_MBOX_NULL;

+  }

+

+  sys_mbox_free(conn->mbox);

+  conn->mbox = SYS_MBOX_NULL;

+  if (conn->sem != SYS_SEM_NULL) {

+    sys_sem_free(conn->sem);

+  }

+  /*  conn->sem = SYS_SEM_NULL;*/

+  memp_free(MEMP_NETCONN, conn);

+  return ERR_OK;

+}

+

+enum netconn_type

+netconn_type(struct netconn *conn)

+{

+  return conn->type;

+}

+

+err_t

+netconn_peer(struct netconn *conn, struct ip_addr *addr,

+       u16_t *port)

+{

+  switch (conn->type) {

+  case NETCONN_RAW:

+    /* return an error as connecting is only a helper for upper layers */

+    return ERR_CONN;

+  case NETCONN_UDPLITE:

+  case NETCONN_UDPNOCHKSUM:

+  case NETCONN_UDP:

+    if (conn->pcb.udp == NULL ||

+  ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))

+     return ERR_CONN;

+    *addr = (conn->pcb.udp->remote_ip);

+    *port = conn->pcb.udp->remote_port;

+    break;

+  case NETCONN_TCP:

+    if (conn->pcb.tcp == NULL)

+      return ERR_CONN;

+    *addr = (conn->pcb.tcp->remote_ip);

+    *port = conn->pcb.tcp->remote_port;

+    break;

+  }

+  return (conn->err = ERR_OK);

+}

+

+err_t

+netconn_addr(struct netconn *conn, struct ip_addr **addr,

+       u16_t *port)

+{

+  switch (conn->type) {

+  case NETCONN_RAW:

+    *addr = &(conn->pcb.raw->local_ip);

+    *port = conn->pcb.raw->protocol;

+    break;

+  case NETCONN_UDPLITE:

+  case NETCONN_UDPNOCHKSUM:

+  case NETCONN_UDP:

+    *addr = &(conn->pcb.udp->local_ip);

+    *port = conn->pcb.udp->local_port;

+    break;

+  case NETCONN_TCP:

+    *addr = &(conn->pcb.tcp->local_ip);

+    *port = conn->pcb.tcp->local_port;

+    break;

+  }

+  return (conn->err = ERR_OK);

+}

+

+err_t

+netconn_bind(struct netconn *conn, struct ip_addr *addr,

+      u16_t port)

+{

+  struct api_msg *msg;

+

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+

+  if (conn->type != NETCONN_TCP &&

+     conn->recvmbox == SYS_MBOX_NULL) {

+    if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {

+      return ERR_MEM;

+    }

+  }

+  

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return (conn->err = ERR_MEM);

+  }

+  msg->type = API_MSG_BIND;

+  msg->msg.conn = conn;

+  msg->msg.msg.bc.ipaddr = addr;

+  msg->msg.msg.bc.port = port;

+  api_msg_post(msg);

+  sys_mbox_fetch(conn->mbox, NULL);

+  memp_free(MEMP_API_MSG, msg);

+  return conn->err;

+}

+

+

+err_t

+netconn_connect(struct netconn *conn, struct ip_addr *addr,

+       u16_t port)

+{

+  struct api_msg *msg;

+  

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+

+

+  if (conn->recvmbox == SYS_MBOX_NULL) {

+    if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {

+      return ERR_MEM;

+    }

+  }

+  

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return ERR_MEM;

+  }

+  msg->type = API_MSG_CONNECT;

+  msg->msg.conn = conn;  

+  msg->msg.msg.bc.ipaddr = addr;

+  msg->msg.msg.bc.port = port;

+  api_msg_post(msg);

+  sys_mbox_fetch(conn->mbox, NULL);

+  memp_free(MEMP_API_MSG, msg);

+  return conn->err;

+}

+

+err_t

+netconn_disconnect(struct netconn *conn)

+{

+  struct api_msg *msg;

+  

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return ERR_MEM;

+  }

+  msg->type = API_MSG_DISCONNECT;

+  msg->msg.conn = conn;  

+  api_msg_post(msg);

+  sys_mbox_fetch(conn->mbox, NULL);

+  memp_free(MEMP_API_MSG, msg);

+  return conn->err;

+

+}

+

+err_t

+netconn_listen(struct netconn *conn)

+{

+  struct api_msg *msg;

+

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+

+  if (conn->acceptmbox == SYS_MBOX_NULL) {

+    conn->acceptmbox = sys_mbox_new();

+    if (conn->acceptmbox == SYS_MBOX_NULL) {

+      return ERR_MEM;

+    }

+  }

+  

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return (conn->err = ERR_MEM);

+  }

+  msg->type = API_MSG_LISTEN;

+  msg->msg.conn = conn;

+  api_msg_post(msg);

+  sys_mbox_fetch(conn->mbox, NULL);

+  memp_free(MEMP_API_MSG, msg);

+  return conn->err;

+}

+

+struct netconn *

+netconn_accept(struct netconn *conn)

+{

+  struct netconn *newconn;

+  

+  if (conn == NULL) {

+    return NULL;

+  }

+  

+  sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);

+  /* Register event with callback */

+  if (conn->callback)

+      (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);

+  

+  return newconn;

+}

+

+struct netbuf *

+netconn_recv(struct netconn *conn)

+{

+  struct api_msg *msg;

+  struct netbuf *buf;

+  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);

+

+    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. */

+    if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+      conn->err = ERR_MEM;

+      return buf;

+    }

+    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);

+    memp_free(MEMP_API_MSG, msg);

+  } else {

+    sys_mbox_fetch(conn->recvmbox, (void **)&buf);

+  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;

+}

+

+err_t

+netconn_send(struct netconn *conn, struct netbuf *buf)

+{

+  struct api_msg *msg;

+

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+

+  if (conn->err != ERR_OK) {

+    return conn->err;

+  }

+

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return (conn->err = ERR_MEM);

+  }

+

+  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;

+  api_msg_post(msg);

+

+  sys_mbox_fetch(conn->mbox, NULL);

+  memp_free(MEMP_API_MSG, msg);

+  return conn->err;

+}

+

+err_t

+netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)

+{

+  struct api_msg *msg;

+  u16_t len;

+  

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+

+  if (conn->err != ERR_OK) {

+    return conn->err;

+  }

+  

+  if (conn->sem == SYS_SEM_NULL) {

+    conn->sem = sys_sem_new(0);

+    if (conn->sem == SYS_SEM_NULL) {

+      return ERR_MEM;

+    }

+  }

+

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return (conn->err = ERR_MEM);

+  }

+  msg->type = API_MSG_WRITE;

+  msg->msg.conn = conn;

+        

+

+  conn->state = NETCONN_WRITE;

+  while (conn->err == ERR_OK && size > 0) {

+    msg->msg.msg.w.dataptr = dataptr;

+    msg->msg.msg.w.copy = copy;

+    

+    if (conn->type == NETCONN_TCP) {

+      if (tcp_sndbuf(conn->pcb.tcp) == 0) {

+  sys_sem_wait(conn->sem);

+  if (conn->err != ERR_OK) {

+    goto ret;

+  }

+      }

+      if (size > tcp_sndbuf(conn->pcb.tcp)) {

+  /* We cannot send more than one send buffer's worth of data at a

+     time. */

+  len = tcp_sndbuf(conn->pcb.tcp);

+      } else {

+  len = size;

+      }

+    } else {

+      len = size;

+    }

+    

+    LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));

+    msg->msg.msg.w.len = len;

+    api_msg_post(msg);

+    sys_mbox_fetch(conn->mbox, NULL);    

+    if (conn->err == ERR_OK) {

+      dataptr = (void *)((u8_t *)dataptr + len);

+      size -= len;

+    } else if (conn->err == ERR_MEM) {

+      conn->err = ERR_OK;

+      sys_sem_wait(conn->sem);

+    } else {

+      goto ret;

+    }

+  }

+ ret:

+  memp_free(MEMP_API_MSG, msg);

+  conn->state = NETCONN_NONE;

+  if (conn->sem != SYS_SEM_NULL) {

+    sys_sem_free(conn->sem);

+    conn->sem = SYS_SEM_NULL;

+  }

+  

+  return conn->err;

+}

+

+err_t

+netconn_close(struct netconn *conn)

+{

+  struct api_msg *msg;

+

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {

+    return (conn->err = ERR_MEM);

+  }

+

+  conn->state = NETCONN_CLOSE;

+ again:

+  msg->type = API_MSG_CLOSE;

+  msg->msg.conn = conn;

+  api_msg_post(msg);

+  sys_mbox_fetch(conn->mbox, NULL);

+  if (conn->err == ERR_MEM &&

+     conn->sem != SYS_SEM_NULL) {

+    sys_sem_wait(conn->sem);

+    goto again;

+  }

+  conn->state = NETCONN_NONE;

+  memp_free(MEMP_API_MSG, msg);

+  return conn->err;

+}

+

+err_t

+netconn_err(struct netconn *conn)

+{

+  return conn->err;

+}

+

diff --git a/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_msg.c b/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_msg.c
index 0cbe626..9b9bf9c 100644
--- a/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_msg.c
+++ b/Demo/lwIP_MCF5235_GCC/lwip/src/api/api_msg.c
@@ -1,800 +1,800 @@
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-#include "lwip/arch.h"
-#include "lwip/api_msg.h"
-#include "lwip/memp.h"
-#include "lwip/sys.h"
-#include "lwip/tcpip.h"
-
-#if LWIP_RAW
-static u8_t
-recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
-    struct ip_addr *addr)
-{
-  struct netbuf *buf;
-  struct netconn *conn;
-
-  conn = arg;
-  if (!conn) return 0;
-
-  if (conn->recvmbox != SYS_MBOX_NULL) {
-    if (!(buf = memp_malloc(MEMP_NETBUF))) {
-      return 0;
-    }
-    pbuf_ref(p);
-    buf->p = p;
-    buf->ptr = p;
-    buf->fromaddr = addr;
-    buf->fromport = pcb->protocol;
-
-    conn->recv_avail += p->tot_len;
-    /* Register event with callback */
-    if (conn->callback)
-        (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
-    sys_mbox_post(conn->recvmbox, buf);
-  }
-
-  return 0; /* do not eat the packet */
-}
-#endif
-#if LWIP_UDP
-static void
-recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
-   struct ip_addr *addr, u16_t port)
-{
-  struct netbuf *buf;
-  struct netconn *conn;
-
-  conn = arg;
-  
-  if (conn == NULL) {
-    pbuf_free(p);
-    return;
-  }
-  if (conn->recvmbox != SYS_MBOX_NULL) {
-    buf = memp_malloc(MEMP_NETBUF);
-    if (buf == NULL) {
-      pbuf_free(p);
-      return;
-    } else {
-      buf->p = p;
-      buf->ptr = p;
-      buf->fromaddr = addr;
-      buf->fromport = port;
-    }
-
-  conn->recv_avail += p->tot_len;
-    /* Register event with callback */
-    if (conn->callback)
-        (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
-    sys_mbox_post(conn->recvmbox, buf);
-  }
-}
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-
-static err_t
-recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
-{
-  struct netconn *conn;
-  u16_t len;
-  
-  conn = arg;
-
-  if (conn == NULL) {
-    pbuf_free(p);
-    return ERR_VAL;
-  }
-
-  if (conn->recvmbox != SYS_MBOX_NULL) {
-        
-    conn->err = err;
-    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_RCVPLUS, len);
-    sys_mbox_post(conn->recvmbox, p);
-  }  
-  return ERR_OK;
-}
-
-
-static err_t
-poll_tcp(void *arg, struct tcp_pcb *pcb)
-{
-  struct netconn *conn;
-
-  conn = arg;
-  if (conn != NULL &&
-     (conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&
-     conn->sem != SYS_SEM_NULL) {
-    sys_sem_signal(conn->sem);
-  }
-  return ERR_OK;
-}
-
-static err_t
-sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
-{
-  struct netconn *conn;
-
-  conn = arg;
-  if (conn != NULL && conn->sem != SYS_SEM_NULL) {
-    sys_sem_signal(conn->sem);
-  }
-
-  if (conn && conn->callback)
-      if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)
-          (*conn->callback)(conn, NETCONN_EVT_SENDPLUS, len);
-  
-  return ERR_OK;
-}
-
-static void
-err_tcp(void *arg, err_t err)
-{
-  struct netconn *conn;
-
-  conn = arg;
-
-  conn->pcb.tcp = NULL;
-
-  
-  conn->err = err;
-  if (conn->recvmbox != SYS_MBOX_NULL) {
-    /* Register event with callback */
-    if (conn->callback)
-      (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
-    sys_mbox_post(conn->recvmbox, NULL);
-  }
-  if (conn->mbox != SYS_MBOX_NULL) {
-    sys_mbox_post(conn->mbox, NULL);
-  }
-  if (conn->acceptmbox != SYS_MBOX_NULL) {
-     /* Register event with callback */
-    if (conn->callback)
-      (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
-    sys_mbox_post(conn->acceptmbox, NULL);
-  }
-  if (conn->sem != SYS_SEM_NULL) {
-    sys_sem_signal(conn->sem);
-  }
-}
-
-static void
-setup_tcp(struct netconn *conn)
-{
-  struct tcp_pcb *pcb;
-  
-  pcb = conn->pcb.tcp;
-  tcp_arg(pcb, conn);
-  tcp_recv(pcb, recv_tcp);
-  tcp_sent(pcb, sent_tcp);
-  tcp_poll(pcb, poll_tcp, 4);
-  tcp_err(pcb, err_tcp);
-}
-
-static err_t
-accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
-{
-  sys_mbox_t mbox;
-  struct netconn *newconn;
-  struct netconn *conn;
-  
-#if API_MSG_DEBUG
-#if TCP_DEBUG
-  tcp_debug_print_state(newpcb->state);
-#endif /* TCP_DEBUG */
-#endif /* API_MSG_DEBUG */
-  conn = (struct netconn *)arg;
-  mbox = conn->acceptmbox;
-  newconn = memp_malloc(MEMP_NETCONN);
-  if (newconn == NULL) {
-    return ERR_MEM;
-  }
-  newconn->type = NETCONN_TCP;
-  newconn->pcb.tcp = newpcb;
-  setup_tcp(newconn);
-  newconn->recvmbox = sys_mbox_new();
-  if (newconn->recvmbox == SYS_MBOX_NULL) {
-    memp_free(MEMP_NETCONN, newconn);
-    return ERR_MEM;
-  }
-  newconn->mbox = sys_mbox_new();
-  if (newconn->mbox == SYS_MBOX_NULL) {
-    sys_mbox_free(newconn->recvmbox);
-    memp_free(MEMP_NETCONN, newconn);
-    return ERR_MEM;
-  }
-  newconn->sem = sys_sem_new(0);
-  if (newconn->sem == SYS_SEM_NULL) {
-    sys_mbox_free(newconn->recvmbox);
-    sys_mbox_free(newconn->mbox);
-    memp_free(MEMP_NETCONN, newconn);
-    return ERR_MEM;
-  }
-  newconn->acceptmbox = SYS_MBOX_NULL;
-  newconn->err = err;
-  /* Register event with callback */
-  if (conn->callback)
-  {
-    (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
-    /* We have to set the callback here even though
-     * the new socket is unknown. Mark the socket as -1. */
-    newconn->callback = conn->callback;
-    newconn->socket = -1;
-  }
-  
-  sys_mbox_post(mbox, newconn);
-  return ERR_OK;
-}
-#endif /* LWIP_TCP */
-
-static void
-do_newconn(struct api_msg_msg *msg)
-{
-   if(msg->conn->pcb.tcp != NULL) {
-   /* This "new" connection already has a PCB allocated. */
-   /* Is this an error condition? Should it be deleted? 
-      We currently just are happy and return. */
-     sys_mbox_post(msg->conn->mbox, NULL);
-     return;
-   }
-
-   msg->conn->err = ERR_OK;
-
-   /* Allocate a PCB for this connection */
-   switch(msg->conn->type) {
-#if LWIP_RAW
-   case NETCONN_RAW:
-      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */
-      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
-     break;
-#endif
-#if LWIP_UDP
-   case NETCONN_UDPLITE:
-      msg->conn->pcb.udp = udp_new();
-      if(msg->conn->pcb.udp == NULL) {
-         msg->conn->err = ERR_MEM;
-         break;
-      }
-      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-   case NETCONN_UDPNOCHKSUM:
-      msg->conn->pcb.udp = udp_new();
-      if(msg->conn->pcb.udp == NULL) {
-         msg->conn->err = ERR_MEM;
-         break;
-      }
-      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-   case NETCONN_UDP:
-      msg->conn->pcb.udp = udp_new();
-      if(msg->conn->pcb.udp == NULL) {
-         msg->conn->err = ERR_MEM;
-         break;
-      }
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-   case NETCONN_TCP:
-      msg->conn->pcb.tcp = tcp_new();
-      if(msg->conn->pcb.tcp == NULL) {
-         msg->conn->err = ERR_MEM;
-         break;
-      }
-      setup_tcp(msg->conn);
-      break;
-#endif
-   }
-   
-  
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-
-
-static void
-do_delconn(struct api_msg_msg *msg)
-{
-  if (msg->conn->pcb.tcp != NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      raw_remove(msg->conn->pcb.raw);
-      break;
-#endif
-#if LWIP_UDP
-    case NETCONN_UDPLITE:
-      /* FALLTHROUGH */
-    case NETCONN_UDPNOCHKSUM:
-      /* FALLTHROUGH */
-    case NETCONN_UDP:
-      msg->conn->pcb.udp->recv_arg = NULL;
-      udp_remove(msg->conn->pcb.udp);
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP      
-    case NETCONN_TCP:
-      if (msg->conn->pcb.tcp->state == LISTEN) {
-  tcp_arg(msg->conn->pcb.tcp, NULL);
-  tcp_accept(msg->conn->pcb.tcp, NULL);  
-  tcp_close(msg->conn->pcb.tcp);
-      } else {
-  tcp_arg(msg->conn->pcb.tcp, NULL);
-  tcp_sent(msg->conn->pcb.tcp, NULL);
-  tcp_recv(msg->conn->pcb.tcp, NULL);  
-  tcp_poll(msg->conn->pcb.tcp, NULL, 0);
-  tcp_err(msg->conn->pcb.tcp, NULL);
-  if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) {
-    tcp_abort(msg->conn->pcb.tcp);
-  }
-      }
-#endif
-    default:  
-    break;
-    }
-  }
-  /* Trigger select() in socket layer */
-  if (msg->conn->callback)
-  {
-      (*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0);
-      (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0);
-  }
-  
-  if (msg->conn->mbox != SYS_MBOX_NULL) {
-    sys_mbox_post(msg->conn->mbox, NULL);
-  }
-}
-
-static void
-do_bind(struct api_msg_msg *msg)
-{
-  if (msg->conn->pcb.tcp == NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
-      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
-      break;
-#endif
-#if LWIP_UDP
-    case NETCONN_UDPLITE:
-      msg->conn->pcb.udp = udp_new();
-      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-    case NETCONN_UDPNOCHKSUM:
-      msg->conn->pcb.udp = udp_new();
-      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-    case NETCONN_UDP:
-      msg->conn->pcb.udp = udp_new();
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP      
-    case NETCONN_TCP:
-      msg->conn->pcb.tcp = tcp_new();
-      setup_tcp(msg->conn);
-#endif /* LWIP_TCP */
-    default:  
-    break;
-    }
-  }
-  switch (msg->conn->type) {
-#if LWIP_RAW
-  case NETCONN_RAW:
-    msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
-    break;
-#endif
-#if LWIP_UDP
-  case NETCONN_UDPLITE:
-    /* FALLTHROUGH */
-  case NETCONN_UDPNOCHKSUM:
-    /* FALLTHROUGH */
-  case NETCONN_UDP:
-    msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
-    break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-  case NETCONN_TCP:
-    msg->conn->err = tcp_bind(msg->conn->pcb.tcp,
-            msg->msg.bc.ipaddr, msg->msg.bc.port);
-#endif /* LWIP_TCP */
-  default:
-    break;
-  }
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-#if LWIP_TCP
-
-static err_t
-do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
-{
-  struct netconn *conn;
-
-  conn = arg;
-
-  if (conn == NULL) {
-    return ERR_VAL;
-  }
-  
-  conn->err = err;
-  if (conn->type == NETCONN_TCP && err == ERR_OK) {
-    setup_tcp(conn);
-  }    
-  sys_mbox_post(conn->mbox, NULL);
-  return ERR_OK;
-}
-#endif  
-
-static void
-do_connect(struct api_msg_msg *msg)
-{
-  if (msg->conn->pcb.tcp == NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
-      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
-      break;
-#endif
-#if LWIP_UDP
-    case NETCONN_UDPLITE:
-      msg->conn->pcb.udp = udp_new();
-      if (msg->conn->pcb.udp == NULL) {
-  msg->conn->err = ERR_MEM;
-  sys_mbox_post(msg->conn->mbox, NULL);
-  return;
-      }
-      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-    case NETCONN_UDPNOCHKSUM:
-      msg->conn->pcb.udp = udp_new();
-      if (msg->conn->pcb.udp == NULL) {
-  msg->conn->err = ERR_MEM;
-  sys_mbox_post(msg->conn->mbox, NULL);
-  return;
-      }
-      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-    case NETCONN_UDP:
-      msg->conn->pcb.udp = udp_new();
-      if (msg->conn->pcb.udp == NULL) {
-  msg->conn->err = ERR_MEM;
-  sys_mbox_post(msg->conn->mbox, NULL);
-  return;
-      }
-      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP      
-    case NETCONN_TCP:
-      msg->conn->pcb.tcp = tcp_new();      
-      if (msg->conn->pcb.tcp == NULL) {
-  msg->conn->err = ERR_MEM;
-  sys_mbox_post(msg->conn->mbox, NULL);
-  return;
-      }
-#endif
-    default:
-      break;
-    }
-  }
-  switch (msg->conn->type) {
-#if LWIP_RAW
-  case NETCONN_RAW:
-    raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
-    sys_mbox_post(msg->conn->mbox, NULL);
-    break;
-#endif
-#if LWIP_UDP
-  case NETCONN_UDPLITE:
-    /* FALLTHROUGH */
-  case NETCONN_UDPNOCHKSUM:
-    /* FALLTHROUGH */
-  case NETCONN_UDP:
-    udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
-    sys_mbox_post(msg->conn->mbox, NULL);
-    break;
-#endif 
-#if LWIP_TCP      
-  case NETCONN_TCP:
-    /*    tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
-    setup_tcp(msg->conn);
-    tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
-    do_connected);
-    /*tcp_output(msg->conn->pcb.tcp);*/
-#endif
-
-  default:
-    break;
-  }
-}
-
-static void
-do_disconnect(struct api_msg_msg *msg)
-{
-
-  switch (msg->conn->type) {
-#if LWIP_RAW
-  case NETCONN_RAW:
-    /* Do nothing as connecting is only a helper for upper lwip layers */
-    break;
-#endif
-#if LWIP_UDP
-  case NETCONN_UDPLITE:
-    /* FALLTHROUGH */
-  case NETCONN_UDPNOCHKSUM:
-    /* FALLTHROUGH */
-  case NETCONN_UDP:
-    udp_disconnect(msg->conn->pcb.udp);
-    break;
-#endif 
-  case NETCONN_TCP:
-    break;
-  }
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-
-
-static void
-do_listen(struct api_msg_msg *msg)
-{
-  if (msg->conn->pcb.tcp != NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
-      break;
-#endif
-#if LWIP_UDP
-    case NETCONN_UDPLITE:
-      /* FALLTHROUGH */
-    case NETCONN_UDPNOCHKSUM:
-      /* FALLTHROUGH */
-    case NETCONN_UDP:
-      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP      
-    case NETCONN_TCP:
-      msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
-      if (msg->conn->pcb.tcp == NULL) {
-  msg->conn->err = ERR_MEM;
-      } else {
-  if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
-    msg->conn->acceptmbox = sys_mbox_new();
-    if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
-      msg->conn->err = ERR_MEM;
-      break;
-    }
-  }
-  tcp_arg(msg->conn->pcb.tcp, msg->conn);
-  tcp_accept(msg->conn->pcb.tcp, accept_function);
-      }
-#endif
-    default:
-      break;
-    }
-  }
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-
-static void
-do_accept(struct api_msg_msg *msg)
-{
-  if (msg->conn->pcb.tcp != NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
-      break;
-#endif
-#if LWIP_UDP
-    case NETCONN_UDPLITE:
-      /* FALLTHROUGH */
-    case NETCONN_UDPNOCHKSUM:
-      /* FALLTHROUGH */
-    case NETCONN_UDP:    
-      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
-      break;
-#endif /* LWIP_UDP */
-    case NETCONN_TCP:
-      break;
-    }
-  }
-}
-
-static void
-do_send(struct api_msg_msg *msg)
-{
-  if (msg->conn->pcb.tcp != NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      raw_send(msg->conn->pcb.raw, msg->msg.p);
-      break;
-#endif
-#if LWIP_UDP
-    case NETCONN_UDPLITE:
-      /* FALLTHROUGH */
-    case NETCONN_UDPNOCHKSUM:
-      /* FALLTHROUGH */
-    case NETCONN_UDP:
-      udp_send(msg->conn->pcb.udp, msg->msg.p);
-      break;
-#endif /* LWIP_UDP */
-    case NETCONN_TCP:
-      break;
-    }
-  }
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-
-static void
-do_recv(struct api_msg_msg *msg)
-{
-#if LWIP_TCP
-  if (msg->conn->pcb.tcp != NULL) {
-    if (msg->conn->type == NETCONN_TCP) {
-      tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
-    }
-  }
-#endif  
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-
-static void
-do_write(struct api_msg_msg *msg)
-{
-#if LWIP_TCP  
-  err_t err;
-#endif  
-  if (msg->conn->pcb.tcp != NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      msg->conn->err = ERR_VAL;
-      break;
-#endif
-#if LWIP_UDP 
-    case NETCONN_UDPLITE:
-      /* FALLTHROUGH */
-    case NETCONN_UDPNOCHKSUM:
-      /* FALLTHROUGH */
-    case NETCONN_UDP:
-      msg->conn->err = ERR_VAL;
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP 
-    case NETCONN_TCP:      
-      err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
-                      msg->msg.w.len, msg->msg.w.copy);
-      /* This is the Nagle algorithm: inhibit the sending of new TCP
-   segments when new outgoing data arrives from the user if any
-   previously transmitted data on the connection remains
-   unacknowledged. */
-      if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {
-  tcp_output(msg->conn->pcb.tcp);
-      }
-      msg->conn->err = err;
-      if (msg->conn->callback)
-          if (err == ERR_OK)
-          {
-              if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT)
-                  (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len);
-          }
-#endif
-    default:
-      break;
-    }
-  }
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-
-static void
-do_close(struct api_msg_msg *msg)
-{
-  err_t err;
-
-  err = ERR_OK;
-
-  if (msg->conn->pcb.tcp != NULL) {
-    switch (msg->conn->type) {
-#if LWIP_RAW
-    case NETCONN_RAW:
-      break;
-#endif
-#if LWIP_UDP
-    case NETCONN_UDPLITE:
-      /* FALLTHROUGH */
-    case NETCONN_UDPNOCHKSUM:
-      /* FALLTHROUGH */
-    case NETCONN_UDP:
-      break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
-    case NETCONN_TCP:
-      if (msg->conn->pcb.tcp->state == LISTEN) {
-  err = tcp_close(msg->conn->pcb.tcp);
-      }
-      msg->conn->err = err;      
-#endif
-    default:      
-      break;
-    }
-  }
-  sys_mbox_post(msg->conn->mbox, NULL);
-}
-
-typedef void (* api_msg_decode)(struct api_msg_msg *msg);
-static api_msg_decode decode[API_MSG_MAX] = {
-  do_newconn,
-  do_delconn,
-  do_bind,
-  do_connect,
-  do_disconnect,
-  do_listen,
-  do_accept,
-  do_send,
-  do_recv,
-  do_write,
-  do_close
-  };
-void
-api_msg_input(struct api_msg *msg)
-{  
-  decode[msg->type](&(msg->msg));
-}
-
-void
-api_msg_post(struct api_msg *msg)
-{
-  tcpip_apimsg(msg);
-}
-
-
-
+/*

+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.

+ * All rights reserved. 

+ * 

+ * Redistribution and use in source and binary forms, with or without modification, 

+ * are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice,

+ *    this list of conditions and the following disclaimer.

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ * 3. The name of the author may not be used to endorse or promote products

+ *    derived from this software without specific prior written permission. 

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 

+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 

+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 

+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 

+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 

+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 

+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 

+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 

+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 

+ * OF SUCH DAMAGE.

+ *

+ * This file is part of the lwIP TCP/IP stack.

+ * 

+ * Author: Adam Dunkels <adam@sics.se>

+ *

+ */

+

+#include "lwip/opt.h"

+#include "lwip/arch.h"

+#include "lwip/api_msg.h"

+#include "lwip/memp.h"

+#include "lwip/sys.h"

+#include "lwip/tcpip.h"

+

+#if LWIP_RAW

+static u8_t

+recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,

+    struct ip_addr *addr)

+{

+  struct netbuf *buf;

+  struct netconn *conn;

+

+  conn = arg;

+  if (!conn) return 0;

+

+  if (conn->recvmbox != SYS_MBOX_NULL) {

+    if (!(buf = memp_malloc(MEMP_NETBUF))) {

+      return 0;

+    }

+    pbuf_ref(p);

+    buf->p = p;

+    buf->ptr = p;

+    buf->fromaddr = addr;

+    buf->fromport = pcb->protocol;

+

+    conn->recv_avail += p->tot_len;

+    /* Register event with callback */

+    if (conn->callback)

+        (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);

+    sys_mbox_post(conn->recvmbox, buf);

+  }

+

+  return 0; /* do not eat the packet */

+}

+#endif

+#if LWIP_UDP

+static void

+recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,

+   struct ip_addr *addr, u16_t port)

+{

+  struct netbuf *buf;

+  struct netconn *conn;

+

+  conn = arg;

+  

+  if (conn == NULL) {

+    pbuf_free(p);

+    return;

+  }

+  if (conn->recvmbox != SYS_MBOX_NULL) {

+    buf = memp_malloc(MEMP_NETBUF);

+    if (buf == NULL) {

+      pbuf_free(p);

+      return;

+    } else {

+      buf->p = p;

+      buf->ptr = p;

+      buf->fromaddr = addr;

+      buf->fromport = port;

+    }

+

+  conn->recv_avail += p->tot_len;

+    /* Register event with callback */

+    if (conn->callback)

+        (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);

+    sys_mbox_post(conn->recvmbox, buf);

+  }

+}

+#endif /* LWIP_UDP */

+#if LWIP_TCP

+

+static err_t

+recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)

+{

+  struct netconn *conn;

+  u16_t len;

+  

+  conn = arg;

+

+  if (conn == NULL) {

+    pbuf_free(p);

+    return ERR_VAL;

+  }

+

+  if (conn->recvmbox != SYS_MBOX_NULL) {

+        

+    conn->err = err;

+    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_RCVPLUS, len);

+    sys_mbox_post(conn->recvmbox, p);

+  }  

+  return ERR_OK;

+}

+

+

+static err_t

+poll_tcp(void *arg, struct tcp_pcb *pcb)

+{

+  struct netconn *conn;

+

+  conn = arg;

+  if (conn != NULL &&

+     (conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&

+     conn->sem != SYS_SEM_NULL) {

+    sys_sem_signal(conn->sem);

+  }

+  return ERR_OK;

+}

+

+static err_t

+sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)

+{

+  struct netconn *conn;

+

+  conn = arg;

+  if (conn != NULL && conn->sem != SYS_SEM_NULL) {

+    sys_sem_signal(conn->sem);

+  }

+

+  if (conn && conn->callback)

+      if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)

+          (*conn->callback)(conn, NETCONN_EVT_SENDPLUS, len);

+  

+  return ERR_OK;

+}

+

+static void

+err_tcp(void *arg, err_t err)

+{

+  struct netconn *conn;

+

+  conn = arg;

+

+  conn->pcb.tcp = NULL;

+

+  

+  conn->err = err;

+  if (conn->recvmbox != SYS_MBOX_NULL) {

+    /* Register event with callback */

+    if (conn->callback)

+      (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);

+    sys_mbox_post(conn->recvmbox, NULL);

+  }

+  if (conn->mbox != SYS_MBOX_NULL) {

+    sys_mbox_post(conn->mbox, NULL);

+  }

+  if (conn->acceptmbox != SYS_MBOX_NULL) {

+     /* Register event with callback */

+    if (conn->callback)

+      (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);

+    sys_mbox_post(conn->acceptmbox, NULL);

+  }

+  if (conn->sem != SYS_SEM_NULL) {

+    sys_sem_signal(conn->sem);

+  }

+}

+

+static void

+setup_tcp(struct netconn *conn)

+{

+  struct tcp_pcb *pcb;

+  

+  pcb = conn->pcb.tcp;

+  tcp_arg(pcb, conn);

+  tcp_recv(pcb, recv_tcp);

+  tcp_sent(pcb, sent_tcp);

+  tcp_poll(pcb, poll_tcp, 4);

+  tcp_err(pcb, err_tcp);

+}

+

+static err_t

+accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)

+{

+  sys_mbox_t mbox;

+  struct netconn *newconn;

+  struct netconn *conn;

+  

+#if API_MSG_DEBUG

+#if TCP_DEBUG

+  tcp_debug_print_state(newpcb->state);

+#endif /* TCP_DEBUG */

+#endif /* API_MSG_DEBUG */

+  conn = (struct netconn *)arg;

+  mbox = conn->acceptmbox;

+  newconn = memp_malloc(MEMP_NETCONN);

+  if (newconn == NULL) {

+    return ERR_MEM;

+  }

+  newconn->type = NETCONN_TCP;

+  newconn->pcb.tcp = newpcb;

+  setup_tcp(newconn);

+  newconn->recvmbox = sys_mbox_new();

+  if (newconn->recvmbox == SYS_MBOX_NULL) {

+    memp_free(MEMP_NETCONN, newconn);

+    return ERR_MEM;

+  }

+  newconn->mbox = sys_mbox_new();

+  if (newconn->mbox == SYS_MBOX_NULL) {

+    sys_mbox_free(newconn->recvmbox);

+    memp_free(MEMP_NETCONN, newconn);

+    return ERR_MEM;

+  }

+  newconn->sem = sys_sem_new(0);

+  if (newconn->sem == SYS_SEM_NULL) {

+    sys_mbox_free(newconn->recvmbox);

+    sys_mbox_free(newconn->mbox);

+    memp_free(MEMP_NETCONN, newconn);

+    return ERR_MEM;

+  }

+  newconn->acceptmbox = SYS_MBOX_NULL;

+  newconn->err = err;

+  /* Register event with callback */

+  if (conn->callback)

+  {

+    (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);

+    /* We have to set the callback here even though

+     * the new socket is unknown. Mark the socket as -1. */

+    newconn->callback = conn->callback;

+    newconn->socket = -1;

+  }

+  

+  sys_mbox_post(mbox, newconn);

+  return ERR_OK;

+}

+#endif /* LWIP_TCP */

+

+static void

+do_newconn(struct api_msg_msg *msg)

+{

+   if(msg->conn->pcb.tcp != NULL) {

+   /* This "new" connection already has a PCB allocated. */

+   /* Is this an error condition? Should it be deleted? 

+      We currently just are happy and return. */

+     sys_mbox_post(msg->conn->mbox, NULL);

+     return;

+   }

+

+   msg->conn->err = ERR_OK;

+

+   /* Allocate a PCB for this connection */

+   switch(msg->conn->type) {

+#if LWIP_RAW

+   case NETCONN_RAW:

+      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */

+      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);

+     break;

+#endif

+#if LWIP_UDP

+   case NETCONN_UDPLITE:

+      msg->conn->pcb.udp = udp_new();

+      if(msg->conn->pcb.udp == NULL) {

+         msg->conn->err = ERR_MEM;

+         break;

+      }

+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+   case NETCONN_UDPNOCHKSUM:

+      msg->conn->pcb.udp = udp_new();

+      if(msg->conn->pcb.udp == NULL) {

+         msg->conn->err = ERR_MEM;

+         break;

+      }

+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+   case NETCONN_UDP:

+      msg->conn->pcb.udp = udp_new();

+      if(msg->conn->pcb.udp == NULL) {

+         msg->conn->err = ERR_MEM;

+         break;

+      }

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP

+   case NETCONN_TCP:

+      msg->conn->pcb.tcp = tcp_new();

+      if(msg->conn->pcb.tcp == NULL) {

+         msg->conn->err = ERR_MEM;

+         break;

+      }

+      setup_tcp(msg->conn);

+      break;

+#endif

+   }

+   

+  

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+

+

+static void

+do_delconn(struct api_msg_msg *msg)

+{

+  if (msg->conn->pcb.tcp != NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      raw_remove(msg->conn->pcb.raw);

+      break;

+#endif

+#if LWIP_UDP

+    case NETCONN_UDPLITE:

+      /* FALLTHROUGH */

+    case NETCONN_UDPNOCHKSUM:

+      /* FALLTHROUGH */

+    case NETCONN_UDP:

+      msg->conn->pcb.udp->recv_arg = NULL;

+      udp_remove(msg->conn->pcb.udp);

+      break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP      

+    case NETCONN_TCP:

+      if (msg->conn->pcb.tcp->state == LISTEN) {

+  tcp_arg(msg->conn->pcb.tcp, NULL);

+  tcp_accept(msg->conn->pcb.tcp, NULL);  

+  tcp_close(msg->conn->pcb.tcp);

+      } else {

+  tcp_arg(msg->conn->pcb.tcp, NULL);

+  tcp_sent(msg->conn->pcb.tcp, NULL);

+  tcp_recv(msg->conn->pcb.tcp, NULL);  

+  tcp_poll(msg->conn->pcb.tcp, NULL, 0);

+  tcp_err(msg->conn->pcb.tcp, NULL);

+  if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) {

+    tcp_abort(msg->conn->pcb.tcp);

+  }

+      }

+#endif

+    default:  

+    break;

+    }

+  }

+  /* Trigger select() in socket layer */

+  if (msg->conn->callback)

+  {

+      (*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0);

+      (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0);

+  }

+  

+  if (msg->conn->mbox != SYS_MBOX_NULL) {

+    sys_mbox_post(msg->conn->mbox, NULL);

+  }

+}

+

+static void

+do_bind(struct api_msg_msg *msg)

+{

+  if (msg->conn->pcb.tcp == NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */

+      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);

+      break;

+#endif

+#if LWIP_UDP

+    case NETCONN_UDPLITE:

+      msg->conn->pcb.udp = udp_new();

+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+    case NETCONN_UDPNOCHKSUM:

+      msg->conn->pcb.udp = udp_new();

+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+    case NETCONN_UDP:

+      msg->conn->pcb.udp = udp_new();

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP      

+    case NETCONN_TCP:

+      msg->conn->pcb.tcp = tcp_new();

+      setup_tcp(msg->conn);

+#endif /* LWIP_TCP */

+    default:  

+    break;

+    }

+  }

+  switch (msg->conn->type) {

+#if LWIP_RAW

+  case NETCONN_RAW:

+    msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);

+    break;

+#endif

+#if LWIP_UDP

+  case NETCONN_UDPLITE:

+    /* FALLTHROUGH */

+  case NETCONN_UDPNOCHKSUM:

+    /* FALLTHROUGH */

+  case NETCONN_UDP:

+    msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);

+    break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP

+  case NETCONN_TCP:

+    msg->conn->err = tcp_bind(msg->conn->pcb.tcp,

+            msg->msg.bc.ipaddr, msg->msg.bc.port);

+#endif /* LWIP_TCP */

+  default:

+    break;

+  }

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+#if LWIP_TCP

+

+static err_t

+do_connected(void *arg, struct tcp_pcb *pcb, err_t err)

+{

+  struct netconn *conn;

+

+  conn = arg;

+

+  if (conn == NULL) {

+    return ERR_VAL;

+  }

+  

+  conn->err = err;

+  if (conn->type == NETCONN_TCP && err == ERR_OK) {

+    setup_tcp(conn);

+  }    

+  sys_mbox_post(conn->mbox, NULL);

+  return ERR_OK;

+}

+#endif  

+

+static void

+do_connect(struct api_msg_msg *msg)

+{

+  if (msg->conn->pcb.tcp == NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */

+      raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);

+      break;

+#endif

+#if LWIP_UDP

+    case NETCONN_UDPLITE:

+      msg->conn->pcb.udp = udp_new();

+      if (msg->conn->pcb.udp == NULL) {

+  msg->conn->err = ERR_MEM;

+  sys_mbox_post(msg->conn->mbox, NULL);

+  return;

+      }

+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+    case NETCONN_UDPNOCHKSUM:

+      msg->conn->pcb.udp = udp_new();

+      if (msg->conn->pcb.udp == NULL) {

+  msg->conn->err = ERR_MEM;

+  sys_mbox_post(msg->conn->mbox, NULL);

+  return;

+      }

+      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+    case NETCONN_UDP:

+      msg->conn->pcb.udp = udp_new();

+      if (msg->conn->pcb.udp == NULL) {

+  msg->conn->err = ERR_MEM;

+  sys_mbox_post(msg->conn->mbox, NULL);

+  return;

+      }

+      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);

+      break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP      

+    case NETCONN_TCP:

+      msg->conn->pcb.tcp = tcp_new();      

+      if (msg->conn->pcb.tcp == NULL) {

+  msg->conn->err = ERR_MEM;

+  sys_mbox_post(msg->conn->mbox, NULL);

+  return;

+      }

+#endif

+    default:

+      break;

+    }

+  }

+  switch (msg->conn->type) {

+#if LWIP_RAW

+  case NETCONN_RAW:

+    raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);

+    sys_mbox_post(msg->conn->mbox, NULL);

+    break;

+#endif

+#if LWIP_UDP

+  case NETCONN_UDPLITE:

+    /* FALLTHROUGH */

+  case NETCONN_UDPNOCHKSUM:

+    /* FALLTHROUGH */

+  case NETCONN_UDP:

+    udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);

+    sys_mbox_post(msg->conn->mbox, NULL);

+    break;

+#endif 

+#if LWIP_TCP      

+  case NETCONN_TCP:

+    /*    tcp_arg(msg->conn->pcb.tcp, msg->conn);*/

+    setup_tcp(msg->conn);

+    tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,

+    do_connected);

+    /*tcp_output(msg->conn->pcb.tcp);*/

+#endif

+

+  default:

+    break;

+  }

+}

+

+static void

+do_disconnect(struct api_msg_msg *msg)

+{

+

+  switch (msg->conn->type) {

+#if LWIP_RAW

+  case NETCONN_RAW:

+    /* Do nothing as connecting is only a helper for upper lwip layers */

+    break;

+#endif

+#if LWIP_UDP

+  case NETCONN_UDPLITE:

+    /* FALLTHROUGH */

+  case NETCONN_UDPNOCHKSUM:

+    /* FALLTHROUGH */

+  case NETCONN_UDP:

+    udp_disconnect(msg->conn->pcb.udp);

+    break;

+#endif 

+  case NETCONN_TCP:

+    break;

+  }

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+

+

+static void

+do_listen(struct api_msg_msg *msg)

+{

+  if (msg->conn->pcb.tcp != NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));

+      break;

+#endif

+#if LWIP_UDP

+    case NETCONN_UDPLITE:

+      /* FALLTHROUGH */

+    case NETCONN_UDPNOCHKSUM:

+      /* FALLTHROUGH */

+    case NETCONN_UDP:

+      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));

+      break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP      

+    case NETCONN_TCP:

+      msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);

+      if (msg->conn->pcb.tcp == NULL) {

+  msg->conn->err = ERR_MEM;

+      } else {

+  if (msg->conn->acceptmbox == SYS_MBOX_NULL) {

+    msg->conn->acceptmbox = sys_mbox_new();

+    if (msg->conn->acceptmbox == SYS_MBOX_NULL) {

+      msg->conn->err = ERR_MEM;

+      break;

+    }

+  }

+  tcp_arg(msg->conn->pcb.tcp, msg->conn);

+  tcp_accept(msg->conn->pcb.tcp, accept_function);

+      }

+#endif

+    default:

+      break;

+    }

+  }

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+

+static void

+do_accept(struct api_msg_msg *msg)

+{

+  if (msg->conn->pcb.tcp != NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));

+      break;

+#endif

+#if LWIP_UDP

+    case NETCONN_UDPLITE:

+      /* FALLTHROUGH */

+    case NETCONN_UDPNOCHKSUM:

+      /* FALLTHROUGH */

+    case NETCONN_UDP:    

+      LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));

+      break;

+#endif /* LWIP_UDP */

+    case NETCONN_TCP:

+      break;

+    }

+  }

+}

+

+static void

+do_send(struct api_msg_msg *msg)

+{

+  if (msg->conn->pcb.tcp != NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      raw_send(msg->conn->pcb.raw, msg->msg.p);

+      break;

+#endif

+#if LWIP_UDP

+    case NETCONN_UDPLITE:

+      /* FALLTHROUGH */

+    case NETCONN_UDPNOCHKSUM:

+      /* FALLTHROUGH */

+    case NETCONN_UDP:

+      udp_send(msg->conn->pcb.udp, msg->msg.p);

+      break;

+#endif /* LWIP_UDP */

+    case NETCONN_TCP:

+      break;

+    }

+  }

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+

+static void

+do_recv(struct api_msg_msg *msg)

+{

+#if LWIP_TCP

+  if (msg->conn->pcb.tcp != NULL) {

+    if (msg->conn->type == NETCONN_TCP) {

+      tcp_recved(msg->conn->pcb.tcp, msg->msg.len);

+    }

+  }

+#endif  

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+

+static void

+do_write(struct api_msg_msg *msg)

+{

+#if LWIP_TCP  

+  err_t err;

+#endif  

+  if (msg->conn->pcb.tcp != NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      msg->conn->err = ERR_VAL;

+      break;

+#endif

+#if LWIP_UDP 

+    case NETCONN_UDPLITE:

+      /* FALLTHROUGH */

+    case NETCONN_UDPNOCHKSUM:

+      /* FALLTHROUGH */

+    case NETCONN_UDP:

+      msg->conn->err = ERR_VAL;

+      break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP 

+    case NETCONN_TCP:      

+      err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,

+                      msg->msg.w.len, msg->msg.w.copy);

+      /* This is the Nagle algorithm: inhibit the sending of new TCP

+   segments when new outgoing data arrives from the user if any

+   previously transmitted data on the connection remains

+   unacknowledged. */

+      if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {

+  tcp_output(msg->conn->pcb.tcp);

+      }

+      msg->conn->err = err;

+      if (msg->conn->callback)

+          if (err == ERR_OK)

+          {

+              if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT)

+                  (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len);

+          }

+#endif

+    default:

+      break;

+    }

+  }

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+

+static void

+do_close(struct api_msg_msg *msg)

+{

+  err_t err;

+

+  err = ERR_OK;

+

+  if (msg->conn->pcb.tcp != NULL) {

+    switch (msg->conn->type) {

+#if LWIP_RAW

+    case NETCONN_RAW:

+      break;

+#endif

+#if LWIP_UDP

+    case NETCONN_UDPLITE:

+      /* FALLTHROUGH */

+    case NETCONN_UDPNOCHKSUM:

+      /* FALLTHROUGH */

+    case NETCONN_UDP:

+      break;

+#endif /* LWIP_UDP */

+#if LWIP_TCP

+    case NETCONN_TCP:

+      if (msg->conn->pcb.tcp->state == LISTEN) {

+  err = tcp_close(msg->conn->pcb.tcp);

+      }

+      msg->conn->err = err;      

+#endif

+    default:      

+      break;

+    }

+  }

+  sys_mbox_post(msg->conn->mbox, NULL);

+}

+

+typedef void (* api_msg_decode)(struct api_msg_msg *msg);

+static api_msg_decode decode[API_MSG_MAX] = {

+  do_newconn,

+  do_delconn,

+  do_bind,

+  do_connect,

+  do_disconnect,

+  do_listen,

+  do_accept,

+  do_send,

+  do_recv,

+  do_write,

+  do_close

+  };

+void

+api_msg_input(struct api_msg *msg)

+{  

+  decode[msg->type](&(msg->msg));

+}

+

+void

+api_msg_post(struct api_msg *msg)

+{

+  tcpip_apimsg(msg);

+}

+

+

+

diff --git a/Demo/lwIP_MCF5235_GCC/lwip/src/api/err.c b/Demo/lwIP_MCF5235_GCC/lwip/src/api/err.c
index b582d88..cc63678 100644
--- a/Demo/lwIP_MCF5235_GCC/lwip/src/api/err.c
+++ b/Demo/lwIP_MCF5235_GCC/lwip/src/api/err.c
@@ -1,59 +1,59 @@
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/err.h"
-
-#ifdef LWIP_DEBUG
-
-static char *err_strerr[] = {"Ok.",
-           "Out of memory error.",
-           "Buffer error.",
-           "Connection aborted.",
-           "Connection reset.",
-           "Connection closed.",
-           "Not connected.",
-           "Illegal value.",
-           "Illegal argument.",
-           "Routing problem.",
-           "Address in use."
-};
-
-
-char *
-lwip_strerr(err_t err)
-{
-  return err_strerr[-err];
-
-}
-
-
-#endif /* LWIP_DEBUG */
+/*

+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.

+ * All rights reserved. 

+ * 

+ * Redistribution and use in source and binary forms, with or without modification, 

+ * are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice,

+ *    this list of conditions and the following disclaimer.

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ * 3. The name of the author may not be used to endorse or promote products

+ *    derived from this software without specific prior written permission. 

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 

+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 

+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 

+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 

+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 

+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 

+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 

+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 

+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 

+ * OF SUCH DAMAGE.

+ *

+ * This file is part of the lwIP TCP/IP stack.

+ * 

+ * Author: Adam Dunkels <adam@sics.se>

+ *

+ */

+

+#include "lwip/err.h"

+

+#ifdef LWIP_DEBUG

+

+static char *err_strerr[] = {"Ok.",

+           "Out of memory error.",

+           "Buffer error.",

+           "Connection aborted.",

+           "Connection reset.",

+           "Connection closed.",

+           "Not connected.",

+           "Illegal value.",

+           "Illegal argument.",

+           "Routing problem.",

+           "Address in use."

+};

+

+

+char *

+lwip_strerr(err_t err)

+{

+  return err_strerr[-err];

+

+}

+

+

+#endif /* LWIP_DEBUG */

diff --git a/Demo/lwIP_MCF5235_GCC/lwip/src/api/sockets.c b/Demo/lwIP_MCF5235_GCC/lwip/src/api/sockets.c
index 290a7b7..26e6d86 100644
--- a/Demo/lwIP_MCF5235_GCC/lwip/src/api/sockets.c
+++ b/Demo/lwIP_MCF5235_GCC/lwip/src/api/sockets.c
@@ -1,1362 +1,1362 @@
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
- *
- */
-
-#include <string.h>
-#include <errno.h>
-
-#include "lwip/opt.h"
-#include "lwip/api.h"
-#include "lwip/arch.h"
-#include "lwip/sys.h"
-
-#include "lwip/sockets.h"
-
-#define NUM_SOCKETS MEMP_NUM_NETCONN
-
-struct lwip_socket {
-  struct netconn *conn;
-  struct netbuf *lastdata;
-  u16_t lastoffset;
-  u16_t rcvevent;
-  u16_t sendevent;
-  u16_t  flags;
-  int err;
-};
-
-struct lwip_select_cb
-{
-    struct lwip_select_cb *next;
-    fd_set *readset;
-    fd_set *writeset;
-    fd_set *exceptset;
-    int sem_signalled;
-    sys_sem_t sem;
-};
-
-static struct lwip_socket sockets[NUM_SOCKETS];
-static struct lwip_select_cb *select_cb_list = 0;
-
-static sys_sem_t socksem = 0;
-static sys_sem_t selectsem = 0;
-
-static void
-event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
-
-static int err_to_errno_table[11] = {
-    0,      /* ERR_OK    0      No error, everything OK. */
-    ENOMEM,    /* ERR_MEM  -1      Out of memory error.     */
-    ENOBUFS,    /* ERR_BUF  -2      Buffer error.            */
-    ECONNABORTED,  /* ERR_ABRT -3      Connection aborted.      */
-    ECONNRESET,    /* ERR_RST  -4      Connection reset.        */
-    ESHUTDOWN,    /* ERR_CLSD -5      Connection closed.       */
-    ENOTCONN,    /* ERR_CONN -6      Not connected.           */
-    EINVAL,    /* ERR_VAL  -7      Illegal value.           */
-    EIO,    /* ERR_ARG  -8      Illegal argument.        */
-    EHOSTUNREACH,  /* ERR_RTE  -9      Routing problem.         */
-    EADDRINUSE    /* ERR_USE  -10     Address in use.          */
-};
-
-#define ERR_TO_ERRNO_TABLE_SIZE \
-  (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
-
-#define err_to_errno(err) \
-  (-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \
-    err_to_errno_table[-(err)] : EIO)
-
-#ifdef ERRNO
-#define set_errno(err) errno = (err)
-#else
-#define set_errno(err)
-#endif
-
-#define sock_set_errno(sk, e) do { \
-      sk->err = (e); \
-      set_errno(sk->err); \
-} while (0)
-
-
-static struct lwip_socket *
-get_socket(int s)
-{
-  struct lwip_socket *sock;
-
-  if ((s < 0) || (s > NUM_SOCKETS)) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
-    set_errno(EBADF);
-    return NULL;
-  }
-
-  sock = &sockets[s];
-
-  if (!sock->conn) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
-    set_errno(EBADF);
-    return NULL;
-  }
-
-  return sock;
-}
-
-static int
-alloc_socket(struct netconn *newconn)
-{
-  int i;
-
-  if (!socksem)
-      socksem = sys_sem_new(1);
-
-  /* Protect socket array */
-  sys_sem_wait(socksem);
-
-  /* allocate a new socket identifier */
-  for(i = 0; i < NUM_SOCKETS; ++i) {
-    if (!sockets[i].conn) {
-      sockets[i].conn = newconn;
-      sockets[i].lastdata = NULL;
-      sockets[i].lastoffset = 0;
-      sockets[i].rcvevent = 0;
-      sockets[i].sendevent = 1; /* TCP send buf is empty */
-      sockets[i].flags = 0;
-      sockets[i].err = 0;
-      sys_sem_signal(socksem);
-      return i;
-    }
-  }
-  sys_sem_signal(socksem);
-  return -1;
-}
-
-int
-lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
-{
-  struct lwip_socket *sock;
-  struct netconn *newconn;
-  struct ip_addr naddr;
-  u16_t port;
-  int newsock;
-  struct sockaddr_in sin;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  newconn = netconn_accept(sock->conn);
-
-  /* get the IP address and port of the remote host */
-  netconn_peer(newconn, &naddr, &port);
-
-  memset(&sin, 0, sizeof(sin));
-  sin.sin_len = sizeof(sin);
-  sin.sin_family = AF_INET;
-  sin.sin_port = htons(port);
-  sin.sin_addr.s_addr = naddr.addr;
-
-  if (*addrlen > sizeof(sin))
-      *addrlen = sizeof(sin);
-
-  memcpy(addr, &sin, *addrlen);
-
-  newsock = alloc_socket(newconn);
-  if (newsock == -1) {
-    netconn_delete(newconn);
-  sock_set_errno(sock, ENOBUFS);
-  return -1;
-  }
-  newconn->callback = event_callback;
-  sock = get_socket(newsock);
-
-  sys_sem_wait(socksem);
-  sock->rcvevent += -1 - newconn->socket;
-  newconn->socket = newsock;
-  sys_sem_signal(socksem);
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
-  ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
-
-  sock_set_errno(sock, 0);
-  return newsock;
-}
-
-int
-lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
-{
-  struct lwip_socket *sock;
-  struct ip_addr local_addr;
-  u16_t local_port;
-  err_t err;
-
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
-  local_port = ((struct sockaddr_in *)name)->sin_port;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
-  ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
-
-  err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
-
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int
-lwip_close(int s)
-{
-  struct lwip_socket *sock;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
-  if (!socksem)
-      socksem = sys_sem_new(1);
-
-  /* We cannot allow multiple closes of the same socket. */
-  sys_sem_wait(socksem);
-
-  sock = get_socket(s);
-  if (!sock) {
-      sys_sem_signal(socksem);
-      set_errno(EBADF);
-      return -1;
-  }
-
-  netconn_delete(sock->conn);
-  if (sock->lastdata) {
-    netbuf_delete(sock->lastdata);
-  }
-  sock->lastdata = NULL;
-  sock->lastoffset = 0;
-  sock->conn = NULL;
-  sys_sem_signal(socksem);
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int
-lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
-{
-  struct lwip_socket *sock;
-  err_t err;
-
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
-    err = netconn_disconnect(sock->conn);
-  } else {
-    struct ip_addr remote_addr;
-    u16_t remote_port;
-
-    remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
-    remote_port = ((struct sockaddr_in *)name)->sin_port;
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
-    ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
-    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
-
-    err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
-   }
-
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int
-lwip_listen(int s, int backlog)
-{
-  struct lwip_socket *sock;
-  err_t err;
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  err = netconn_listen(sock->conn);
-
-  if (err != ERR_OK) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
-    sock_set_errno(sock, err_to_errno(err));
-    return -1;
-  }
-
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int
-lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
-        struct sockaddr *from, socklen_t *fromlen)
-{
-  struct lwip_socket *sock;
-  struct netbuf *buf;
-  u16_t buflen, copylen;
-  struct ip_addr *addr;
-  u16_t port;
-
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  /* Check if there is data left from the last recv operation. */
-  if (sock->lastdata) {
-    buf = sock->lastdata;
-  } else {
-    /* If this is non-blocking call, then check first */
-    if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK))
-  && !sock->rcvevent)
-    {
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
-      sock_set_errno(sock, EWOULDBLOCK);
-      return -1;
-    }
-
-    /* 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, 0);
-      return 0;
-    }
-  }
-
-  buflen = netbuf_len(buf);
-
-  buflen -= sock->lastoffset;
-
-  if (len > buflen) {
-    copylen = buflen;
-  } else {
-    copylen = len;
-  }
-
-  /* copy the contents of the received buffer into
-     the supplied memory pointer mem */
-  netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
-
-  /* Check to see from where the data was. */
-  if (from && fromlen) {
-    struct sockaddr_in sin;
-
-    addr = netbuf_fromaddr(buf);
-    port = netbuf_fromport(buf);
-
-    memset(&sin, 0, sizeof(sin));
-    sin.sin_len = sizeof(sin);
-    sin.sin_family = AF_INET;
-    sin.sin_port = htons(port);
-    sin.sin_addr.s_addr = addr->addr;
-
-    if (*fromlen > sizeof(sin))
-      *fromlen = sizeof(sin);
-
-    memcpy(from, &sin, *fromlen);
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
-    ip_addr_debug_print(SOCKETS_DEBUG, addr);
-    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
-  } else {
-#if SOCKETS_DEBUG
-    addr = netbuf_fromaddr(buf);
-    port = netbuf_fromport(buf);
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
-    ip_addr_debug_print(SOCKETS_DEBUG, addr);
-    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
-#endif
-
-  }
-
-  /* If this is a TCP socket, check if there is data left in the
-     buffer. If so, it should be saved in the sock structure for next
-     time around. */
-  if (netconn_type(sock->conn) == NETCONN_TCP && buflen - copylen > 0) {
-    sock->lastdata = buf;
-    sock->lastoffset += copylen;
-  } else {
-    sock->lastdata = NULL;
-    sock->lastoffset = 0;
-    netbuf_delete(buf);
-  }
-
-
-  sock_set_errno(sock, 0);
-  return copylen;
-}
-
-int
-lwip_read(int s, void *mem, int len)
-{
-  return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
-}
-
-int
-lwip_recv(int s, void *mem, int len, unsigned int flags)
-{
-  return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
-}
-
-int
-lwip_send(int s, 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));
-
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    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 */
-    netbuf_ref(buf, data, size);
-
-    /* send the data */
-    err = netconn_send(sock->conn, buf);
-
-    /* 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;
-}
-
-int
-lwip_sendto(int s, void *data, int size, unsigned int flags,
-       struct sockaddr *to, socklen_t tolen)
-{
-  struct lwip_socket *sock;
-  struct ip_addr remote_addr, addr;
-  u16_t remote_port, port;
-  int ret,connected;
-
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  /* get the peer if currently connected */
-  connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);
-
-  remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
-  remote_port = ((struct sockaddr_in *)to)->sin_port;
-
-  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)));
-
-  netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
-
-  ret = lwip_send(s, data, size, flags);
-
-  /* reset the remote address and port number
-     of the connection */
-  if (connected)
-    netconn_connect(sock->conn, &addr, port);
-  else
-  netconn_disconnect(sock->conn);
-  return ret;
-}
-
-int
-lwip_socket(int domain, int type, int protocol)
-{
-  struct netconn *conn;
-  int i;
-
-  /* create a netconn */
-  switch (type) {
-  case SOCK_RAW:
-    conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
-    break;
-  case SOCK_DGRAM:
-    conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
-    break;
-  case SOCK_STREAM:
-    conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
-    break;
-  default:
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, protocol));
-    set_errno(EINVAL);
-    return -1;
-  }
-
-  if (!conn) {
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
-    set_errno(ENOBUFS);
-    return -1;
-  }
-
-  i = alloc_socket(conn);
-
-  if (i == -1) {
-    netconn_delete(conn);
-  set_errno(ENOBUFS);
-  return -1;
-  }
-  conn->socket = i;
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
-  set_errno(0);
-  return i;
-}
-
-int
-lwip_write(int s, void *data, int size)
-{
-   return lwip_send(s, data, size, 0);
-}
-
-
-static int
-lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
-{
-    int i, nready = 0;
-    fd_set lreadset, lwriteset, lexceptset;
-    struct lwip_socket *p_sock;
-
-    FD_ZERO(&lreadset);
-    FD_ZERO(&lwriteset);
-    FD_ZERO(&lexceptset);
-
-    /* Go through each socket in each list to count number of sockets which
-       currently match */
-    for(i = 0; i < maxfdp1; i++)
-    {
-        if (FD_ISSET(i, readset))
-        {
-            /* See if netconn of this socket is ready for read */
-            p_sock = get_socket(i);
-            if (p_sock && (p_sock->lastdata || p_sock->rcvevent))
-            {
-                FD_SET(i, &lreadset);
-		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
-                nready++;
-            }
-        }
-        if (FD_ISSET(i, writeset))
-        {
-            /* See if netconn of this socket is ready for write */
-            p_sock = get_socket(i);
-            if (p_sock && p_sock->sendevent)
-            {
-                FD_SET(i, &lwriteset);
-		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
-                nready++;
-            }
-        }
-    }
-    *readset = lreadset;
-    *writeset = lwriteset;
-    FD_ZERO(exceptset);
-
-    return nready;
-}
-
-
-
-int
-lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
-               struct timeval *timeout)
-{
-    int i;
-    int nready;
-    fd_set lreadset, lwriteset, lexceptset;
-    u32_t msectimeout;
-    struct lwip_select_cb select_cb;
-    struct lwip_select_cb *p_selcb;
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, timeout ? timeout->tv_sec : -1L, timeout ? timeout->tv_usec : -1L));
-
-    select_cb.next = 0;
-    select_cb.readset = readset;
-    select_cb.writeset = writeset;
-    select_cb.exceptset = exceptset;
-    select_cb.sem_signalled = 0;
-
-    /* Protect ourselves searching through the list */
-    if (!selectsem)
-        selectsem = sys_sem_new(1);
-    sys_sem_wait(selectsem);
-
-    if (readset)
-        lreadset = *readset;
-    else
-        FD_ZERO(&lreadset);
-    if (writeset)
-        lwriteset = *writeset;
-    else
-        FD_ZERO(&lwriteset);
-    if (exceptset)
-        lexceptset = *exceptset;
-    else
-        FD_ZERO(&lexceptset);
-
-    /* Go through each socket in each list to count number of sockets which
-       currently match */
-    nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
-
-    /* If we don't have any current events, then suspend if we are supposed to */
-    if (!nready)
-    {
-        if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
-        {
-            sys_sem_signal(selectsem);
-            if (readset)
-                FD_ZERO(readset);
-            if (writeset)
-                FD_ZERO(writeset);
-            if (exceptset)
-                FD_ZERO(exceptset);
-
-	    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
-	    set_errno(0);
-
-            return 0;
-        }
-
-        /* add our semaphore to list */
-        /* We don't actually need any dynamic memory. Our entry on the
-         * list is only valid while we are in this function, so it's ok
-         * to use local variables */
-
-        select_cb.sem = sys_sem_new(0);
-        /* Note that we are still protected */
-        /* Put this select_cb on top of list */
-        select_cb.next = select_cb_list;
-        select_cb_list = &select_cb;
-
-        /* Now we can safely unprotect */
-        sys_sem_signal(selectsem);
-
-        /* Now just wait to be woken */
-        if (timeout == 0)
-            /* Wait forever */
-            msectimeout = 0;
-        else
-            msectimeout =  ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
-
-        i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
-
-        /* Take us off the list */
-        sys_sem_wait(selectsem);
-        if (select_cb_list == &select_cb)
-            select_cb_list = select_cb.next;
-        else
-            for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next)
-                if (p_selcb->next == &select_cb)
-                {
-                    p_selcb->next = select_cb.next;
-                    break;
-                }
-
-        sys_sem_signal(selectsem);
-
-        sys_sem_free(select_cb.sem);
-        if (i == 0)             /* Timeout */
-        {
-            if (readset)
-                FD_ZERO(readset);
-            if (writeset)
-                FD_ZERO(writeset);
-            if (exceptset)
-                FD_ZERO(exceptset);
-
-	    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
-	    set_errno(0);
-
-            return 0;
-        }
-
-        if (readset)
-            lreadset = *readset;
-        else
-            FD_ZERO(&lreadset);
-        if (writeset)
-            lwriteset = *writeset;
-        else
-            FD_ZERO(&lwriteset);
-        if (exceptset)
-            lexceptset = *exceptset;
-        else
-            FD_ZERO(&lexceptset);
-
-        /* See what's set */
-        nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
-    }
-    else
-        sys_sem_signal(selectsem);
-
-    if (readset)
-        *readset = lreadset;
-    if (writeset)
-        *writeset = lwriteset;
-    if (exceptset)
-        *exceptset = lexceptset;
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
-    set_errno(0);
-
-    return nready;
-}
-
-
-static void
-event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
-{
-    int s;
-    struct lwip_socket *sock;
-    struct lwip_select_cb *scb;
-
-    /* Get socket */
-    if (conn)
-    {
-        s = conn->socket;
-        if (s < 0)
-        {
-            /* Data comes in right away after an accept, even though
-             * the server task might not have created a new socket yet.
-             * Just count down (or up) if that's the case and we
-             * will use the data later. Note that only receive events
-             * can happen before the new socket is set up. */
-            if (evt == NETCONN_EVT_RCVPLUS)
-                conn->socket--;
-            return;
-        }
-
-        sock = get_socket(s);
-        if (!sock)
-            return;
-    }
-    else
-        return;
-
-    if (!selectsem)
-        selectsem = sys_sem_new(1);
-
-    sys_sem_wait(selectsem);
-    /* Set event as required */
-    switch (evt)
-    {
-      case NETCONN_EVT_RCVPLUS:
-        sock->rcvevent++;
-        break;
-      case NETCONN_EVT_RCVMINUS:
-        sock->rcvevent--;
-        break;
-      case NETCONN_EVT_SENDPLUS:
-        sock->sendevent = 1;
-        break;
-      case NETCONN_EVT_SENDMINUS:
-        sock->sendevent = 0;
-        break;
-    }
-    sys_sem_signal(selectsem);
-
-    /* Now decide if anyone is waiting for this socket */
-    /* NOTE: This code is written this way to protect the select link list
-       but to avoid a deadlock situation by releasing socksem before
-       signalling for the select. This means we need to go through the list
-       multiple times ONLY IF a select was actually waiting. We go through
-       the list the number of waiting select calls + 1. This list is
-       expected to be small. */
-    while (1)
-    {
-        sys_sem_wait(selectsem);
-        for (scb = select_cb_list; scb; scb = scb->next)
-        {
-            if (scb->sem_signalled == 0)
-            {
-                /* Test this select call for our socket */
-                if (scb->readset && FD_ISSET(s, scb->readset))
-                    if (sock->rcvevent)
-                        break;
-                if (scb->writeset && FD_ISSET(s, scb->writeset))
-                    if (sock->sendevent)
-                        break;
-            }
-        }
-        if (scb)
-        {
-            scb->sem_signalled = 1;
-            sys_sem_signal(selectsem);
-            sys_sem_signal(scb->sem);
-        } else {
-            sys_sem_signal(selectsem);
-            break;
-        }
-    }
-
-}
-
-
-
-
-int lwip_shutdown(int s, int how)
-{
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
-  return lwip_close(s); /* XXX temporary hack until proper implementation */
-}
-
-int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
-{
-  struct lwip_socket *sock;
-  struct sockaddr_in sin;
-  struct ip_addr naddr;
-
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  memset(&sin, 0, sizeof(sin));
-  sin.sin_len = sizeof(sin);
-  sin.sin_family = AF_INET;
-
-  /* get the IP address and port of the remote host */
-  netconn_peer(sock->conn, &naddr, &sin.sin_port);
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
-  ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
-
-  sin.sin_port = htons(sin.sin_port);
-  sin.sin_addr.s_addr = naddr.addr;
-
-  if (*namelen > sizeof(sin))
-      *namelen = sizeof(sin);
-
-  memcpy(name, &sin, *namelen);
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
-{
-  struct lwip_socket *sock;
-  struct sockaddr_in sin;
-  struct ip_addr *naddr;
-
-  sock = get_socket(s);
-  if (!sock) {
-    set_errno(EBADF);
-    return -1;
-  }
-
-  memset(&sin, 0, sizeof(sin));
-  sin.sin_len = sizeof(sin);
-  sin.sin_family = AF_INET;
-
-  /* get the IP address and port of the remote host */
-  netconn_addr(sock->conn, &naddr, &sin.sin_port);
-
-  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
-  ip_addr_debug_print(SOCKETS_DEBUG, naddr);
-  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
-
-  sin.sin_port = htons(sin.sin_port);
-  sin.sin_addr.s_addr = naddr->addr;
-
-  if (*namelen > sizeof(sin))
-      *namelen = sizeof(sin);
-
-  memcpy(name, &sin, *namelen);
-  sock_set_errno(sock, 0);
-  return 0;
-}
-
-int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
-{
-  int err = 0;
-  struct lwip_socket *sock = get_socket(s);
-
-  if(!sock) {
-   	set_errno(EBADF);
-    return -1;
-  }
-
-  if( NULL == optval || NULL == optlen ) {
-    sock_set_errno( sock, EFAULT );
-    return -1;
-  }
-
-  /* Do length and type checks for the various options first, to keep it readable. */
-  switch( level ) {
-   
-/* Level: SOL_SOCKET */
-  case SOL_SOCKET:
-      switch(optname) {
-         
-      case SO_ACCEPTCONN:
-      case SO_BROADCAST:
-      /* UNIMPL case SO_DEBUG: */
-      /* UNIMPL case SO_DONTROUTE: */
-      case SO_ERROR:
-      case SO_KEEPALIVE:
-      /* UNIMPL case SO_OOBINLINE: */
-      /* UNIMPL case SO_RCVBUF: */
-      /* UNIMPL case SO_SNDBUF: */
-      /* UNIMPL case SO_RCVLOWAT: */
-      /* UNIMPL case SO_SNDLOWAT: */
-#if SO_REUSE
-      case SO_REUSEADDR:
-      case SO_REUSEPORT:
-#endif /* SO_REUSE */
-      case SO_TYPE:
-      /* UNIMPL case SO_USELOOPBACK: */
-        if( *optlen < sizeof(int) ) {
-          err = EINVAL;
-        }
-          break;
-
-      default:
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
-        err = ENOPROTOOPT;
-      }  /* switch */
-      break;
-                     
-/* Level: IPPROTO_IP */
-  case IPPROTO_IP:
-      switch(optname) {
-      /* UNIMPL case IP_HDRINCL: */
-      /* UNIMPL case IP_RCVDSTADDR: */
-      /* UNIMPL case IP_RCVIF: */
-      case IP_TTL:
-      case IP_TOS:
-        if( *optlen < sizeof(int) ) {
-          err = EINVAL;
-        }
-        break;
-
-      default:
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
-        err = ENOPROTOOPT;
-      }  /* switch */
-      break;
-         
-/* Level: IPPROTO_TCP */
-  case IPPROTO_TCP:
-      if( *optlen < sizeof(int) ) {
-        err = EINVAL;
-        break;
-    }
-      
-      /* If this is no TCP socket, ignore any options. */
-      if ( sock->conn->type != NETCONN_TCP ) return 0;
-
-      switch( optname ) {
-      case TCP_NODELAY:
-      case TCP_KEEPALIVE:
-        break;
-         
-      default:
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
-        err = ENOPROTOOPT;
-      }  /* switch */
-      break;
-
-/* UNDEFINED LEVEL */
-  default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
-      err = ENOPROTOOPT;
-  }  /* switch */
-
-   
-  if( 0 != err ) {
-    sock_set_errno(sock, err);
-    return -1;
-  }
-   
-
-
-  /* Now do the actual option processing */
-
-  switch(level) {
-   
-/* Level: SOL_SOCKET */
-  case SOL_SOCKET:
-    switch( optname ) {
-
-    /* The option flags */
-    case SO_ACCEPTCONN:
-    case SO_BROADCAST:
-    /* UNIMPL case SO_DEBUG: */
-    /* UNIMPL case SO_DONTROUTE: */
-    case SO_KEEPALIVE:
-    /* UNIMPL case SO_OOBINCLUDE: */
-#if SO_REUSE
-    case SO_REUSEADDR:
-    case SO_REUSEPORT:
-#endif /* SO_REUSE */
-    /*case SO_USELOOPBACK: UNIMPL */
-      *(int*)optval = sock->conn->pcb.tcp->so_options & optname;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off")));
-      break;
-
-    case SO_TYPE:
-      switch (sock->conn->type) {
-      case NETCONN_RAW:
-        *(int*)optval = SOCK_RAW;
-        break;
-      case NETCONN_TCP:
-        *(int*)optval = SOCK_STREAM;
-        break;
-      case NETCONN_UDP:
-      case NETCONN_UDPLITE:
-      case NETCONN_UDPNOCHKSUM:
-        *(int*)optval = SOCK_DGRAM;
-        break;
-      default: /* unrecognized socket type */
-        *(int*)optval = sock->conn->type;
-        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s, *(int *)optval));
-      }  /* switch */
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval));
-      break;
-
-    case SO_ERROR:
-      *(int *)optval = sock->err;
-      sock->err = 0;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
-      break;
-    }  /* switch */
-    break;
-
-/* Level: IPPROTO_IP */
-  case IPPROTO_IP:
-    switch( optname ) {
-    case IP_TTL:
-      *(int*)optval = sock->conn->pcb.tcp->ttl;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s, *(int *)optval));
-      break;
-    case IP_TOS:
-      *(int*)optval = sock->conn->pcb.tcp->tos;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval));
-      break;
-    }  /* switch */
-    break;
-
-/* Level: IPPROTO_TCP */
-  case IPPROTO_TCP:
-    switch( optname ) {
-    case TCP_NODELAY:
-      *(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
-      break;
-    case TCP_KEEPALIVE:
-      *(int*)optval = (int)sock->conn->pcb.tcp->keepalive;
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
-      break;
-    }  /* switch */
-    break;
-  }
-
-
-  sock_set_errno(sock, err);
-  return err ? -1 : 0;
-}
-
-int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
-{
-  struct lwip_socket *sock = get_socket(s);
-  int err = 0;
-
-  if(!sock) {
-   	set_errno(EBADF);
-    return -1;
-  }
-
-  if( NULL == optval ) {
-    sock_set_errno( sock, EFAULT );
-    return -1;
-  }
-
-
-  /* Do length and type checks for the various options first, to keep it readable. */
-  switch( level ) {
-
-/* Level: SOL_SOCKET */
-  case SOL_SOCKET:
-    switch(optname) {
-
-    case SO_BROADCAST:
-    /* UNIMPL case SO_DEBUG: */
-    /* UNIMPL case SO_DONTROUTE: */
-    case SO_KEEPALIVE:
-    /* UNIMPL case SO_OOBINLINE: */
-    /* UNIMPL case SO_RCVBUF: */
-    /* UNIMPL case SO_SNDBUF: */
-    /* UNIMPL case SO_RCVLOWAT: */
-    /* UNIMPL case SO_SNDLOWAT: */
-#if SO_REUSE
-    case SO_REUSEADDR:
-    case SO_REUSEPORT:
-#endif /* SO_REUSE */
-    /* UNIMPL case SO_USELOOPBACK: */
-      if( optlen < sizeof(int) ) {
-        err = EINVAL;
-      }
-      break;
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
-      err = ENOPROTOOPT;
-    }  /* switch */
-    break;
-
-/* Level: IPPROTO_IP */
-  case IPPROTO_IP:
-    switch(optname) {
-    /* UNIMPL case IP_HDRINCL: */
-    /* UNIMPL case IP_RCVDSTADDR: */
-    /* UNIMPL case IP_RCVIF: */
-    case IP_TTL:
-    case IP_TOS:
-      if( optlen < sizeof(int) ) {
-        err = EINVAL;
-      }
-        break;
-      default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
-      err = ENOPROTOOPT;
-    }  /* switch */
-    break;
-
-/* Level: IPPROTO_TCP */
-  case IPPROTO_TCP:
-    if( optlen < sizeof(int) ) {
-      err = EINVAL;
-        break;
-    }
-
-    /* If this is no TCP socket, ignore any options. */
-    if ( sock->conn->type != NETCONN_TCP ) return 0;
-
-    switch( optname ) {
-    case TCP_NODELAY:
-    case TCP_KEEPALIVE:
-      break;
-
-    default:
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
-      err = ENOPROTOOPT;
-    }  /* switch */
-    break;
-
-/* UNDEFINED LEVEL */      
-  default:
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
-    err = ENOPROTOOPT;
-  }  /* switch */
-
-
-  if( 0 != err ) {
-    sock_set_errno(sock, err);
-    return -1;
-  }
-
-
-
-  /* Now do the actual option processing */
-
-  switch(level) {
-
-/* Level: SOL_SOCKET */
-  case SOL_SOCKET:
-    switch(optname) {
-
-    /* The option flags */
-    case SO_BROADCAST:
-    /* UNIMPL case SO_DEBUG: */
-    /* UNIMPL case SO_DONTROUTE: */
-    case SO_KEEPALIVE:
-    /* UNIMPL case SO_OOBINCLUDE: */
-#if SO_REUSE
-    case SO_REUSEADDR:
-    case SO_REUSEPORT:
-#endif /* SO_REUSE */
-    /* UNIMPL case SO_USELOOPBACK: */
-      if ( *(int*)optval ) {
-        sock->conn->pcb.tcp->so_options |= optname;
-      } else {
-        sock->conn->pcb.tcp->so_options &= ~optname;
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
-      break;
-    }  /* switch */
-    break;
-
-/* Level: IPPROTO_IP */
-  case IPPROTO_IP:
-    switch( optname ) {
-    case IP_TTL:
-      sock->conn->pcb.tcp->ttl = (u8_t)(*(int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
-      break;
-    case IP_TOS:
-      sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
-      break;
-    }  /* switch */
-    break;
-
-/* Level: IPPROTO_TCP */
-  case IPPROTO_TCP:
-    switch( optname ) {
-    case TCP_NODELAY:
-      if ( *(int*)optval ) {
-        sock->conn->pcb.tcp->flags |= TF_NODELAY;
-      } else {
-        sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
-      }
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );
-      break;
-    case TCP_KEEPALIVE:
-      sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
-      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive));
-      break;
-    }  /* switch */
-    break;
-  }  /* switch */
-
-  sock_set_errno(sock, err);
-  return err ? -1 : 0;
-}
-
-int lwip_ioctl(int s, long cmd, void *argp)
-{
-  struct lwip_socket *sock = get_socket(s);
-
-  if(!sock) {
-   	set_errno(EBADF);
-    return -1;
-  }
-
-  switch (cmd) {
-  case FIONREAD:
-    if (!argp) {
-      sock_set_errno(sock, EINVAL);
-      return -1;
-    }
-
-    *((u16_t*)argp) = sock->conn->recv_avail;
-
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
-    sock_set_errno(sock, 0);
-    return 0;
-
-  case FIONBIO:
-    if (argp && *(u32_t*)argp)
-      sock->flags |= O_NONBLOCK;
-    else
-      sock->flags &= ~O_NONBLOCK;
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
-    sock_set_errno(sock, 0);
-    return 0;
-
-  default:
-    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
-    sock_set_errno(sock, ENOSYS); /* not yet implemented */
-    return -1;
-  }
-}
-
+/*

+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.

+ * All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without modification,

+ * are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice,

+ *    this list of conditions and the following disclaimer.

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ * 3. The name of the author may not be used to endorse or promote products

+ *    derived from this software without specific prior written permission.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED

+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF

+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT

+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,

+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT

+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING

+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY

+ * OF SUCH DAMAGE.

+ *

+ * This file is part of the lwIP TCP/IP stack.

+ *

+ * Author: Adam Dunkels <adam@sics.se>

+ *

+ * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>

+ *

+ */

+

+#include <string.h>

+#include <errno.h>

+

+#include "lwip/opt.h"

+#include "lwip/api.h"

+#include "lwip/arch.h"

+#include "lwip/sys.h"

+

+#include "lwip/sockets.h"

+

+#define NUM_SOCKETS MEMP_NUM_NETCONN

+

+struct lwip_socket {

+  struct netconn *conn;

+  struct netbuf *lastdata;

+  u16_t lastoffset;

+  u16_t rcvevent;

+  u16_t sendevent;

+  u16_t  flags;

+  int err;

+};

+

+struct lwip_select_cb

+{

+    struct lwip_select_cb *next;

+    fd_set *readset;

+    fd_set *writeset;

+    fd_set *exceptset;

+    int sem_signalled;

+    sys_sem_t sem;

+};

+

+static struct lwip_socket sockets[NUM_SOCKETS];

+static struct lwip_select_cb *select_cb_list = 0;

+

+static sys_sem_t socksem = 0;

+static sys_sem_t selectsem = 0;

+

+static void

+event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);

+

+static int err_to_errno_table[11] = {

+    0,      /* ERR_OK    0      No error, everything OK. */

+    ENOMEM,    /* ERR_MEM  -1      Out of memory error.     */

+    ENOBUFS,    /* ERR_BUF  -2      Buffer error.            */

+    ECONNABORTED,  /* ERR_ABRT -3      Connection aborted.      */

+    ECONNRESET,    /* ERR_RST  -4      Connection reset.        */

+    ESHUTDOWN,    /* ERR_CLSD -5      Connection closed.       */

+    ENOTCONN,    /* ERR_CONN -6      Not connected.           */

+    EINVAL,    /* ERR_VAL  -7      Illegal value.           */

+    EIO,    /* ERR_ARG  -8      Illegal argument.        */

+    EHOSTUNREACH,  /* ERR_RTE  -9      Routing problem.         */

+    EADDRINUSE    /* ERR_USE  -10     Address in use.          */

+};

+

+#define ERR_TO_ERRNO_TABLE_SIZE \

+  (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))

+

+#define err_to_errno(err) \

+  (-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \

+    err_to_errno_table[-(err)] : EIO)

+

+#ifdef ERRNO

+#define set_errno(err) errno = (err)

+#else

+#define set_errno(err)

+#endif

+

+#define sock_set_errno(sk, e) do { \

+      sk->err = (e); \

+      set_errno(sk->err); \

+} while (0)

+

+

+static struct lwip_socket *

+get_socket(int s)

+{

+  struct lwip_socket *sock;

+

+  if ((s < 0) || (s > NUM_SOCKETS)) {

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));

+    set_errno(EBADF);

+    return NULL;

+  }

+

+  sock = &sockets[s];

+

+  if (!sock->conn) {

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));

+    set_errno(EBADF);

+    return NULL;

+  }

+

+  return sock;

+}

+

+static int

+alloc_socket(struct netconn *newconn)

+{

+  int i;

+

+  if (!socksem)

+      socksem = sys_sem_new(1);

+

+  /* Protect socket array */

+  sys_sem_wait(socksem);

+

+  /* allocate a new socket identifier */

+  for(i = 0; i < NUM_SOCKETS; ++i) {

+    if (!sockets[i].conn) {

+      sockets[i].conn = newconn;

+      sockets[i].lastdata = NULL;

+      sockets[i].lastoffset = 0;

+      sockets[i].rcvevent = 0;

+      sockets[i].sendevent = 1; /* TCP send buf is empty */

+      sockets[i].flags = 0;

+      sockets[i].err = 0;

+      sys_sem_signal(socksem);

+      return i;

+    }

+  }

+  sys_sem_signal(socksem);

+  return -1;

+}

+

+int

+lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)

+{

+  struct lwip_socket *sock;

+  struct netconn *newconn;

+  struct ip_addr naddr;

+  u16_t port;

+  int newsock;

+  struct sockaddr_in sin;

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  newconn = netconn_accept(sock->conn);

+

+  /* get the IP address and port of the remote host */

+  netconn_peer(newconn, &naddr, &port);

+

+  memset(&sin, 0, sizeof(sin));

+  sin.sin_len = sizeof(sin);

+  sin.sin_family = AF_INET;

+  sin.sin_port = htons(port);

+  sin.sin_addr.s_addr = naddr.addr;

+

+  if (*addrlen > sizeof(sin))

+      *addrlen = sizeof(sin);

+

+  memcpy(addr, &sin, *addrlen);

+

+  newsock = alloc_socket(newconn);

+  if (newsock == -1) {

+    netconn_delete(newconn);

+  sock_set_errno(sock, ENOBUFS);

+  return -1;

+  }

+  newconn->callback = event_callback;

+  sock = get_socket(newsock);

+

+  sys_sem_wait(socksem);

+  sock->rcvevent += -1 - newconn->socket;

+  newconn->socket = newsock;

+  sys_sem_signal(socksem);

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));

+  ip_addr_debug_print(SOCKETS_DEBUG, &naddr);

+  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));

+

+  sock_set_errno(sock, 0);

+  return newsock;

+}

+

+int

+lwip_bind(int s, struct sockaddr *name, socklen_t namelen)

+{

+  struct lwip_socket *sock;

+  struct ip_addr local_addr;

+  u16_t local_port;

+  err_t err;

+

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;

+  local_port = ((struct sockaddr_in *)name)->sin_port;

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));

+  ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);

+  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));

+

+  err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));

+

+  if (err != ERR_OK) {

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));

+    sock_set_errno(sock, err_to_errno(err));

+    return -1;

+  }

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));

+  sock_set_errno(sock, 0);

+  return 0;

+}

+

+int

+lwip_close(int s)

+{

+  struct lwip_socket *sock;

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));

+  if (!socksem)

+      socksem = sys_sem_new(1);

+

+  /* We cannot allow multiple closes of the same socket. */

+  sys_sem_wait(socksem);

+

+  sock = get_socket(s);

+  if (!sock) {

+      sys_sem_signal(socksem);

+      set_errno(EBADF);

+      return -1;

+  }

+

+  netconn_delete(sock->conn);

+  if (sock->lastdata) {

+    netbuf_delete(sock->lastdata);

+  }

+  sock->lastdata = NULL;

+  sock->lastoffset = 0;

+  sock->conn = NULL;

+  sys_sem_signal(socksem);

+  sock_set_errno(sock, 0);

+  return 0;

+}

+

+int

+lwip_connect(int s, struct sockaddr *name, socklen_t namelen)

+{

+  struct lwip_socket *sock;

+  err_t err;

+

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));

+    err = netconn_disconnect(sock->conn);

+  } else {

+    struct ip_addr remote_addr;

+    u16_t remote_port;

+

+    remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;

+    remote_port = ((struct sockaddr_in *)name)->sin_port;

+

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));

+    ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);

+    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));

+

+    err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));

+   }

+

+  if (err != ERR_OK) {

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));

+    sock_set_errno(sock, err_to_errno(err));

+    return -1;

+  }

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));

+  sock_set_errno(sock, 0);

+  return 0;

+}

+

+int

+lwip_listen(int s, int backlog)

+{

+  struct lwip_socket *sock;

+  err_t err;

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  err = netconn_listen(sock->conn);

+

+  if (err != ERR_OK) {

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));

+    sock_set_errno(sock, err_to_errno(err));

+    return -1;

+  }

+

+  sock_set_errno(sock, 0);

+  return 0;

+}

+

+int

+lwip_recvfrom(int s, void *mem, int len, unsigned int flags,

+        struct sockaddr *from, socklen_t *fromlen)

+{

+  struct lwip_socket *sock;

+  struct netbuf *buf;

+  u16_t buflen, copylen;

+  struct ip_addr *addr;

+  u16_t port;

+

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  /* Check if there is data left from the last recv operation. */

+  if (sock->lastdata) {

+    buf = sock->lastdata;

+  } else {

+    /* If this is non-blocking call, then check first */

+    if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK))

+  && !sock->rcvevent)

+    {

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));

+      sock_set_errno(sock, EWOULDBLOCK);

+      return -1;

+    }

+

+    /* 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, 0);

+      return 0;

+    }

+  }

+

+  buflen = netbuf_len(buf);

+

+  buflen -= sock->lastoffset;

+

+  if (len > buflen) {

+    copylen = buflen;

+  } else {

+    copylen = len;

+  }

+

+  /* copy the contents of the received buffer into

+     the supplied memory pointer mem */

+  netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);

+

+  /* Check to see from where the data was. */

+  if (from && fromlen) {

+    struct sockaddr_in sin;

+

+    addr = netbuf_fromaddr(buf);

+    port = netbuf_fromport(buf);

+

+    memset(&sin, 0, sizeof(sin));

+    sin.sin_len = sizeof(sin);

+    sin.sin_family = AF_INET;

+    sin.sin_port = htons(port);

+    sin.sin_addr.s_addr = addr->addr;

+

+    if (*fromlen > sizeof(sin))

+      *fromlen = sizeof(sin);

+

+    memcpy(from, &sin, *fromlen);

+

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));

+    ip_addr_debug_print(SOCKETS_DEBUG, addr);

+    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));

+  } else {

+#if SOCKETS_DEBUG

+    addr = netbuf_fromaddr(buf);

+    port = netbuf_fromport(buf);

+

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));

+    ip_addr_debug_print(SOCKETS_DEBUG, addr);

+    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));

+#endif

+

+  }

+

+  /* If this is a TCP socket, check if there is data left in the

+     buffer. If so, it should be saved in the sock structure for next

+     time around. */

+  if (netconn_type(sock->conn) == NETCONN_TCP && buflen - copylen > 0) {

+    sock->lastdata = buf;

+    sock->lastoffset += copylen;

+  } else {

+    sock->lastdata = NULL;

+    sock->lastoffset = 0;

+    netbuf_delete(buf);

+  }

+

+

+  sock_set_errno(sock, 0);

+  return copylen;

+}

+

+int

+lwip_read(int s, void *mem, int len)

+{

+  return lwip_recvfrom(s, mem, len, 0, NULL, NULL);

+}

+

+int

+lwip_recv(int s, void *mem, int len, unsigned int flags)

+{

+  return lwip_recvfrom(s, mem, len, flags, NULL, NULL);

+}

+

+int

+lwip_send(int s, 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));

+

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    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 */

+    netbuf_ref(buf, data, size);

+

+    /* send the data */

+    err = netconn_send(sock->conn, buf);

+

+    /* 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;

+}

+

+int

+lwip_sendto(int s, void *data, int size, unsigned int flags,

+       struct sockaddr *to, socklen_t tolen)

+{

+  struct lwip_socket *sock;

+  struct ip_addr remote_addr, addr;

+  u16_t remote_port, port;

+  int ret,connected;

+

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  /* get the peer if currently connected */

+  connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);

+

+  remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;

+  remote_port = ((struct sockaddr_in *)to)->sin_port;

+

+  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)));

+

+  netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));

+

+  ret = lwip_send(s, data, size, flags);

+

+  /* reset the remote address and port number

+     of the connection */

+  if (connected)

+    netconn_connect(sock->conn, &addr, port);

+  else

+  netconn_disconnect(sock->conn);

+  return ret;

+}

+

+int

+lwip_socket(int domain, int type, int protocol)

+{

+  struct netconn *conn;

+  int i;

+

+  /* create a netconn */

+  switch (type) {

+  case SOCK_RAW:

+    conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));

+    break;

+  case SOCK_DGRAM:

+    conn = netconn_new_with_callback(NETCONN_UDP, event_callback);

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));

+    break;

+  case SOCK_STREAM:

+    conn = netconn_new_with_callback(NETCONN_TCP, event_callback);

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));

+    break;

+  default:

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, protocol));

+    set_errno(EINVAL);

+    return -1;

+  }

+

+  if (!conn) {

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));

+    set_errno(ENOBUFS);

+    return -1;

+  }

+

+  i = alloc_socket(conn);

+

+  if (i == -1) {

+    netconn_delete(conn);

+  set_errno(ENOBUFS);

+  return -1;

+  }

+  conn->socket = i;

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));

+  set_errno(0);

+  return i;

+}

+

+int

+lwip_write(int s, void *data, int size)

+{

+   return lwip_send(s, data, size, 0);

+}

+

+

+static int

+lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)

+{

+    int i, nready = 0;

+    fd_set lreadset, lwriteset, lexceptset;

+    struct lwip_socket *p_sock;

+

+    FD_ZERO(&lreadset);

+    FD_ZERO(&lwriteset);

+    FD_ZERO(&lexceptset);

+

+    /* Go through each socket in each list to count number of sockets which

+       currently match */

+    for(i = 0; i < maxfdp1; i++)

+    {

+        if (FD_ISSET(i, readset))

+        {

+            /* See if netconn of this socket is ready for read */

+            p_sock = get_socket(i);

+            if (p_sock && (p_sock->lastdata || p_sock->rcvevent))

+            {

+                FD_SET(i, &lreadset);

+		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));

+                nready++;

+            }

+        }

+        if (FD_ISSET(i, writeset))

+        {

+            /* See if netconn of this socket is ready for write */

+            p_sock = get_socket(i);

+            if (p_sock && p_sock->sendevent)

+            {

+                FD_SET(i, &lwriteset);

+		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));

+                nready++;

+            }

+        }

+    }

+    *readset = lreadset;

+    *writeset = lwriteset;

+    FD_ZERO(exceptset);

+

+    return nready;

+}

+

+

+

+int

+lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,

+               struct timeval *timeout)

+{

+    int i;

+    int nready;

+    fd_set lreadset, lwriteset, lexceptset;

+    u32_t msectimeout;

+    struct lwip_select_cb select_cb;

+    struct lwip_select_cb *p_selcb;

+

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, timeout ? timeout->tv_sec : -1L, timeout ? timeout->tv_usec : -1L));

+

+    select_cb.next = 0;

+    select_cb.readset = readset;

+    select_cb.writeset = writeset;

+    select_cb.exceptset = exceptset;

+    select_cb.sem_signalled = 0;

+

+    /* Protect ourselves searching through the list */

+    if (!selectsem)

+        selectsem = sys_sem_new(1);

+    sys_sem_wait(selectsem);

+

+    if (readset)

+        lreadset = *readset;

+    else

+        FD_ZERO(&lreadset);

+    if (writeset)

+        lwriteset = *writeset;

+    else

+        FD_ZERO(&lwriteset);

+    if (exceptset)

+        lexceptset = *exceptset;

+    else

+        FD_ZERO(&lexceptset);

+

+    /* Go through each socket in each list to count number of sockets which

+       currently match */

+    nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);

+

+    /* If we don't have any current events, then suspend if we are supposed to */

+    if (!nready)

+    {

+        if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)

+        {

+            sys_sem_signal(selectsem);

+            if (readset)

+                FD_ZERO(readset);

+            if (writeset)

+                FD_ZERO(writeset);

+            if (exceptset)

+                FD_ZERO(exceptset);

+

+	    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));

+	    set_errno(0);

+

+            return 0;

+        }

+

+        /* add our semaphore to list */

+        /* We don't actually need any dynamic memory. Our entry on the

+         * list is only valid while we are in this function, so it's ok

+         * to use local variables */

+

+        select_cb.sem = sys_sem_new(0);

+        /* Note that we are still protected */

+        /* Put this select_cb on top of list */

+        select_cb.next = select_cb_list;

+        select_cb_list = &select_cb;

+

+        /* Now we can safely unprotect */

+        sys_sem_signal(selectsem);

+

+        /* Now just wait to be woken */

+        if (timeout == 0)

+            /* Wait forever */

+            msectimeout = 0;

+        else

+            msectimeout =  ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));

+

+        i = sys_sem_wait_timeout(select_cb.sem, msectimeout);

+

+        /* Take us off the list */

+        sys_sem_wait(selectsem);

+        if (select_cb_list == &select_cb)

+            select_cb_list = select_cb.next;

+        else

+            for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next)

+                if (p_selcb->next == &select_cb)

+                {

+                    p_selcb->next = select_cb.next;

+                    break;

+                }

+

+        sys_sem_signal(selectsem);

+

+        sys_sem_free(select_cb.sem);

+        if (i == 0)             /* Timeout */

+        {

+            if (readset)

+                FD_ZERO(readset);

+            if (writeset)

+                FD_ZERO(writeset);

+            if (exceptset)

+                FD_ZERO(exceptset);

+

+	    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));

+	    set_errno(0);

+

+            return 0;

+        }

+

+        if (readset)

+            lreadset = *readset;

+        else

+            FD_ZERO(&lreadset);

+        if (writeset)

+            lwriteset = *writeset;

+        else

+            FD_ZERO(&lwriteset);

+        if (exceptset)

+            lexceptset = *exceptset;

+        else

+            FD_ZERO(&lexceptset);

+

+        /* See what's set */

+        nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);

+    }

+    else

+        sys_sem_signal(selectsem);

+

+    if (readset)

+        *readset = lreadset;

+    if (writeset)

+        *writeset = lwriteset;

+    if (exceptset)

+        *exceptset = lexceptset;

+

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));

+    set_errno(0);

+

+    return nready;

+}

+

+

+static void

+event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)

+{

+    int s;

+    struct lwip_socket *sock;

+    struct lwip_select_cb *scb;

+

+    /* Get socket */

+    if (conn)

+    {

+        s = conn->socket;

+        if (s < 0)

+        {

+            /* Data comes in right away after an accept, even though

+             * the server task might not have created a new socket yet.

+             * Just count down (or up) if that's the case and we

+             * will use the data later. Note that only receive events

+             * can happen before the new socket is set up. */

+            if (evt == NETCONN_EVT_RCVPLUS)

+                conn->socket--;

+            return;

+        }

+

+        sock = get_socket(s);

+        if (!sock)

+            return;

+    }

+    else

+        return;

+

+    if (!selectsem)

+        selectsem = sys_sem_new(1);

+

+    sys_sem_wait(selectsem);

+    /* Set event as required */

+    switch (evt)

+    {

+      case NETCONN_EVT_RCVPLUS:

+        sock->rcvevent++;

+        break;

+      case NETCONN_EVT_RCVMINUS:

+        sock->rcvevent--;

+        break;

+      case NETCONN_EVT_SENDPLUS:

+        sock->sendevent = 1;

+        break;

+      case NETCONN_EVT_SENDMINUS:

+        sock->sendevent = 0;

+        break;

+    }

+    sys_sem_signal(selectsem);

+

+    /* Now decide if anyone is waiting for this socket */

+    /* NOTE: This code is written this way to protect the select link list

+       but to avoid a deadlock situation by releasing socksem before

+       signalling for the select. This means we need to go through the list

+       multiple times ONLY IF a select was actually waiting. We go through

+       the list the number of waiting select calls + 1. This list is

+       expected to be small. */

+    while (1)

+    {

+        sys_sem_wait(selectsem);

+        for (scb = select_cb_list; scb; scb = scb->next)

+        {

+            if (scb->sem_signalled == 0)

+            {

+                /* Test this select call for our socket */

+                if (scb->readset && FD_ISSET(s, scb->readset))

+                    if (sock->rcvevent)

+                        break;

+                if (scb->writeset && FD_ISSET(s, scb->writeset))

+                    if (sock->sendevent)

+                        break;

+            }

+        }

+        if (scb)

+        {

+            scb->sem_signalled = 1;

+            sys_sem_signal(selectsem);

+            sys_sem_signal(scb->sem);

+        } else {

+            sys_sem_signal(selectsem);

+            break;

+        }

+    }

+

+}

+

+

+

+

+int lwip_shutdown(int s, int how)

+{

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));

+  return lwip_close(s); /* XXX temporary hack until proper implementation */

+}

+

+int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)

+{

+  struct lwip_socket *sock;

+  struct sockaddr_in sin;

+  struct ip_addr naddr;

+

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  memset(&sin, 0, sizeof(sin));

+  sin.sin_len = sizeof(sin);

+  sin.sin_family = AF_INET;

+

+  /* get the IP address and port of the remote host */

+  netconn_peer(sock->conn, &naddr, &sin.sin_port);

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));

+  ip_addr_debug_print(SOCKETS_DEBUG, &naddr);

+  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));

+

+  sin.sin_port = htons(sin.sin_port);

+  sin.sin_addr.s_addr = naddr.addr;

+

+  if (*namelen > sizeof(sin))

+      *namelen = sizeof(sin);

+

+  memcpy(name, &sin, *namelen);

+  sock_set_errno(sock, 0);

+  return 0;

+}

+

+int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)

+{

+  struct lwip_socket *sock;

+  struct sockaddr_in sin;

+  struct ip_addr *naddr;

+

+  sock = get_socket(s);

+  if (!sock) {

+    set_errno(EBADF);

+    return -1;

+  }

+

+  memset(&sin, 0, sizeof(sin));

+  sin.sin_len = sizeof(sin);

+  sin.sin_family = AF_INET;

+

+  /* get the IP address and port of the remote host */

+  netconn_addr(sock->conn, &naddr, &sin.sin_port);

+

+  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));

+  ip_addr_debug_print(SOCKETS_DEBUG, naddr);

+  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));

+

+  sin.sin_port = htons(sin.sin_port);

+  sin.sin_addr.s_addr = naddr->addr;

+

+  if (*namelen > sizeof(sin))

+      *namelen = sizeof(sin);

+

+  memcpy(name, &sin, *namelen);

+  sock_set_errno(sock, 0);

+  return 0;

+}

+

+int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)

+{

+  int err = 0;

+  struct lwip_socket *sock = get_socket(s);

+

+  if(!sock) {

+   	set_errno(EBADF);

+    return -1;

+  }

+

+  if( NULL == optval || NULL == optlen ) {

+    sock_set_errno( sock, EFAULT );

+    return -1;

+  }

+

+  /* Do length and type checks for the various options first, to keep it readable. */

+  switch( level ) {

+   

+/* Level: SOL_SOCKET */

+  case SOL_SOCKET:

+      switch(optname) {

+         

+      case SO_ACCEPTCONN:

+      case SO_BROADCAST:

+      /* UNIMPL case SO_DEBUG: */

+      /* UNIMPL case SO_DONTROUTE: */

+      case SO_ERROR:

+      case SO_KEEPALIVE:

+      /* UNIMPL case SO_OOBINLINE: */

+      /* UNIMPL case SO_RCVBUF: */

+      /* UNIMPL case SO_SNDBUF: */

+      /* UNIMPL case SO_RCVLOWAT: */

+      /* UNIMPL case SO_SNDLOWAT: */

+#if SO_REUSE

+      case SO_REUSEADDR:

+      case SO_REUSEPORT:

+#endif /* SO_REUSE */

+      case SO_TYPE:

+      /* UNIMPL case SO_USELOOPBACK: */

+        if( *optlen < sizeof(int) ) {

+          err = EINVAL;

+        }

+          break;

+

+      default:

+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));

+        err = ENOPROTOOPT;

+      }  /* switch */

+      break;

+                     

+/* Level: IPPROTO_IP */

+  case IPPROTO_IP:

+      switch(optname) {

+      /* UNIMPL case IP_HDRINCL: */

+      /* UNIMPL case IP_RCVDSTADDR: */

+      /* UNIMPL case IP_RCVIF: */

+      case IP_TTL:

+      case IP_TOS:

+        if( *optlen < sizeof(int) ) {

+          err = EINVAL;

+        }

+        break;

+

+      default:

+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));

+        err = ENOPROTOOPT;

+      }  /* switch */

+      break;

+         

+/* Level: IPPROTO_TCP */

+  case IPPROTO_TCP:

+      if( *optlen < sizeof(int) ) {

+        err = EINVAL;

+        break;

+    }

+      

+      /* If this is no TCP socket, ignore any options. */

+      if ( sock->conn->type != NETCONN_TCP ) return 0;

+

+      switch( optname ) {

+      case TCP_NODELAY:

+      case TCP_KEEPALIVE:

+        break;

+         

+      default:

+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));

+        err = ENOPROTOOPT;

+      }  /* switch */

+      break;

+

+/* UNDEFINED LEVEL */

+  default:

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));

+      err = ENOPROTOOPT;

+  }  /* switch */

+

+   

+  if( 0 != err ) {

+    sock_set_errno(sock, err);

+    return -1;

+  }

+   

+

+

+  /* Now do the actual option processing */

+

+  switch(level) {

+   

+/* Level: SOL_SOCKET */

+  case SOL_SOCKET:

+    switch( optname ) {

+

+    /* The option flags */

+    case SO_ACCEPTCONN:

+    case SO_BROADCAST:

+    /* UNIMPL case SO_DEBUG: */

+    /* UNIMPL case SO_DONTROUTE: */

+    case SO_KEEPALIVE:

+    /* UNIMPL case SO_OOBINCLUDE: */

+#if SO_REUSE

+    case SO_REUSEADDR:

+    case SO_REUSEPORT:

+#endif /* SO_REUSE */

+    /*case SO_USELOOPBACK: UNIMPL */

+      *(int*)optval = sock->conn->pcb.tcp->so_options & optname;

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off")));

+      break;

+

+    case SO_TYPE:

+      switch (sock->conn->type) {

+      case NETCONN_RAW:

+        *(int*)optval = SOCK_RAW;

+        break;

+      case NETCONN_TCP:

+        *(int*)optval = SOCK_STREAM;

+        break;

+      case NETCONN_UDP:

+      case NETCONN_UDPLITE:

+      case NETCONN_UDPNOCHKSUM:

+        *(int*)optval = SOCK_DGRAM;

+        break;

+      default: /* unrecognized socket type */

+        *(int*)optval = sock->conn->type;

+        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s, *(int *)optval));

+      }  /* switch */

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval));

+      break;

+

+    case SO_ERROR:

+      *(int *)optval = sock->err;

+      sock->err = 0;

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));

+      break;

+    }  /* switch */

+    break;

+

+/* Level: IPPROTO_IP */

+  case IPPROTO_IP:

+    switch( optname ) {

+    case IP_TTL:

+      *(int*)optval = sock->conn->pcb.tcp->ttl;

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s, *(int *)optval));

+      break;

+    case IP_TOS:

+      *(int*)optval = sock->conn->pcb.tcp->tos;

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval));

+      break;

+    }  /* switch */

+    break;

+

+/* Level: IPPROTO_TCP */

+  case IPPROTO_TCP:

+    switch( optname ) {

+    case TCP_NODELAY:

+      *(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );

+      break;

+    case TCP_KEEPALIVE:

+      *(int*)optval = (int)sock->conn->pcb.tcp->keepalive;

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));

+      break;

+    }  /* switch */

+    break;

+  }

+

+

+  sock_set_errno(sock, err);

+  return err ? -1 : 0;

+}

+

+int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)

+{

+  struct lwip_socket *sock = get_socket(s);

+  int err = 0;

+

+  if(!sock) {

+   	set_errno(EBADF);

+    return -1;

+  }

+

+  if( NULL == optval ) {

+    sock_set_errno( sock, EFAULT );

+    return -1;

+  }

+

+

+  /* Do length and type checks for the various options first, to keep it readable. */

+  switch( level ) {

+

+/* Level: SOL_SOCKET */

+  case SOL_SOCKET:

+    switch(optname) {

+

+    case SO_BROADCAST:

+    /* UNIMPL case SO_DEBUG: */

+    /* UNIMPL case SO_DONTROUTE: */

+    case SO_KEEPALIVE:

+    /* UNIMPL case SO_OOBINLINE: */

+    /* UNIMPL case SO_RCVBUF: */

+    /* UNIMPL case SO_SNDBUF: */

+    /* UNIMPL case SO_RCVLOWAT: */

+    /* UNIMPL case SO_SNDLOWAT: */

+#if SO_REUSE

+    case SO_REUSEADDR:

+    case SO_REUSEPORT:

+#endif /* SO_REUSE */

+    /* UNIMPL case SO_USELOOPBACK: */

+      if( optlen < sizeof(int) ) {

+        err = EINVAL;

+      }

+      break;

+    default:

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));

+      err = ENOPROTOOPT;

+    }  /* switch */

+    break;

+

+/* Level: IPPROTO_IP */

+  case IPPROTO_IP:

+    switch(optname) {

+    /* UNIMPL case IP_HDRINCL: */

+    /* UNIMPL case IP_RCVDSTADDR: */

+    /* UNIMPL case IP_RCVIF: */

+    case IP_TTL:

+    case IP_TOS:

+      if( optlen < sizeof(int) ) {

+        err = EINVAL;

+      }

+        break;

+      default:

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));

+      err = ENOPROTOOPT;

+    }  /* switch */

+    break;

+

+/* Level: IPPROTO_TCP */

+  case IPPROTO_TCP:

+    if( optlen < sizeof(int) ) {

+      err = EINVAL;

+        break;

+    }

+

+    /* If this is no TCP socket, ignore any options. */

+    if ( sock->conn->type != NETCONN_TCP ) return 0;

+

+    switch( optname ) {

+    case TCP_NODELAY:

+    case TCP_KEEPALIVE:

+      break;

+

+    default:

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));

+      err = ENOPROTOOPT;

+    }  /* switch */

+    break;

+

+/* UNDEFINED LEVEL */      

+  default:

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));

+    err = ENOPROTOOPT;

+  }  /* switch */

+

+

+  if( 0 != err ) {

+    sock_set_errno(sock, err);

+    return -1;

+  }

+

+

+

+  /* Now do the actual option processing */

+

+  switch(level) {

+

+/* Level: SOL_SOCKET */

+  case SOL_SOCKET:

+    switch(optname) {

+

+    /* The option flags */

+    case SO_BROADCAST:

+    /* UNIMPL case SO_DEBUG: */

+    /* UNIMPL case SO_DONTROUTE: */

+    case SO_KEEPALIVE:

+    /* UNIMPL case SO_OOBINCLUDE: */

+#if SO_REUSE

+    case SO_REUSEADDR:

+    case SO_REUSEPORT:

+#endif /* SO_REUSE */

+    /* UNIMPL case SO_USELOOPBACK: */

+      if ( *(int*)optval ) {

+        sock->conn->pcb.tcp->so_options |= optname;

+      } else {

+        sock->conn->pcb.tcp->so_options &= ~optname;

+      }

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));

+      break;

+    }  /* switch */

+    break;

+

+/* Level: IPPROTO_IP */

+  case IPPROTO_IP:

+    switch( optname ) {

+    case IP_TTL:

+      sock->conn->pcb.tcp->ttl = (u8_t)(*(int*)optval);

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));

+      break;

+    case IP_TOS:

+      sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));

+      break;

+    }  /* switch */

+    break;

+

+/* Level: IPPROTO_TCP */

+  case IPPROTO_TCP:

+    switch( optname ) {

+    case TCP_NODELAY:

+      if ( *(int*)optval ) {

+        sock->conn->pcb.tcp->flags |= TF_NODELAY;

+      } else {

+        sock->conn->pcb.tcp->flags &= ~TF_NODELAY;

+      }

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );

+      break;

+    case TCP_KEEPALIVE:

+      sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);

+      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive));

+      break;

+    }  /* switch */

+    break;

+  }  /* switch */

+

+  sock_set_errno(sock, err);

+  return err ? -1 : 0;

+}

+

+int lwip_ioctl(int s, long cmd, void *argp)

+{

+  struct lwip_socket *sock = get_socket(s);

+

+  if(!sock) {

+   	set_errno(EBADF);

+    return -1;

+  }

+

+  switch (cmd) {

+  case FIONREAD:

+    if (!argp) {

+      sock_set_errno(sock, EINVAL);

+      return -1;

+    }

+

+    *((u16_t*)argp) = sock->conn->recv_avail;

+

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));

+    sock_set_errno(sock, 0);

+    return 0;

+

+  case FIONBIO:

+    if (argp && *(u32_t*)argp)

+      sock->flags |= O_NONBLOCK;

+    else

+      sock->flags &= ~O_NONBLOCK;

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));

+    sock_set_errno(sock, 0);

+    return 0;

+

+  default:

+    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));

+    sock_set_errno(sock, ENOSYS); /* not yet implemented */

+    return -1;

+  }

+}

+

diff --git a/Demo/lwIP_MCF5235_GCC/lwip/src/api/tcpip.c b/Demo/lwIP_MCF5235_GCC/lwip/src/api/tcpip.c
index ce8a2ca..db86cf4 100644
--- a/Demo/lwIP_MCF5235_GCC/lwip/src/api/tcpip.c
+++ b/Demo/lwIP_MCF5235_GCC/lwip/src/api/tcpip.c
@@ -1,198 +1,198 @@
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#include "lwip/sys.h"
-
-#include "lwip/memp.h"
-#include "lwip/pbuf.h"
-
-#include "lwip/ip.h"
-#include "lwip/ip_frag.h"
-#include "lwip/udp.h"
-#include "lwip/tcp.h"
-
-#include "lwip/tcpip.h"
-
-static void (* tcpip_init_done)(void *arg) = NULL;
-static void *tcpip_init_done_arg;
-static sys_mbox_t mbox;
-
-#if LWIP_TCP
-static int tcpip_tcp_timer_active = 0;
-
-static void
-tcpip_tcp_timer(void *arg)
-{
-  (void)arg;
-
-  /* call TCP timer handler */
-  tcp_tmr();
-  /* timer still needed? */
-  if (tcp_active_pcbs || tcp_tw_pcbs) {
-    /* restart timer */
-    sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
-  } else {
-    /* disable timer */
-    tcpip_tcp_timer_active = 0;
-  }
-}
-
-#if !NO_SYS
-void
-tcp_timer_needed(void)
-{
-  /* timer is off but needed again? */
-  if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
-    /* enable and start timer */
-    tcpip_tcp_timer_active = 1;
-    sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
-  }
-}
-#endif /* !NO_SYS */
-#endif /* LWIP_TCP */
-
-#if IP_REASSEMBLY
-static void
-ip_timer(void *data)
-{
-  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
-  ip_reass_tmr();
-  sys_timeout(1000, ip_timer, NULL);
-}
-#endif
-
-static void
-tcpip_thread(void *arg)
-{
-  struct tcpip_msg *msg;
-
-  (void)arg;
-
-  ip_init();
-#if LWIP_UDP  
-  udp_init();
-#endif
-#if LWIP_TCP
-  tcp_init();
-#endif
-#if IP_REASSEMBLY
-  sys_timeout(1000, ip_timer, NULL);
-#endif
-  if (tcpip_init_done != NULL) {
-    tcpip_init_done(tcpip_init_done_arg);
-  }
-
-  while (1) {                          /* MAIN Loop */
-    sys_mbox_fetch(mbox, (void *)&msg);
-    switch (msg->type) {
-    case TCPIP_MSG_API:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
-      api_msg_input(msg->msg.apimsg);
-      break;
-    case TCPIP_MSG_INPUT:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg));
-      ip_input(msg->msg.inp.p, msg->msg.inp.netif);
-      break;
-    case TCPIP_MSG_CALLBACK:
-      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
-      msg->msg.cb.f(msg->msg.cb.ctx);
-      break;
-    default:
-      break;
-    }
-    memp_free(MEMP_TCPIP_MSG, msg);
-  }
-}
-
-err_t
-tcpip_input(struct pbuf *p, struct netif *inp)
-{
-  struct tcpip_msg *msg;
-  
-  msg = memp_malloc(MEMP_TCPIP_MSG);
-  if (msg == NULL) {
-    pbuf_free(p);    
-    return ERR_MEM;  
-  }
-  
-  msg->type = TCPIP_MSG_INPUT;
-  msg->msg.inp.p = p;
-  msg->msg.inp.netif = inp;
-  sys_mbox_post(mbox, msg);
-  return ERR_OK;
-}
-
-err_t
-tcpip_callback(void (*f)(void *ctx), void *ctx)
-{
-  struct tcpip_msg *msg;
-  
-  msg = memp_malloc(MEMP_TCPIP_MSG);
-  if (msg == NULL) {
-    return ERR_MEM;  
-  }
-  
-  msg->type = TCPIP_MSG_CALLBACK;
-  msg->msg.cb.f = f;
-  msg->msg.cb.ctx = ctx;
-  sys_mbox_post(mbox, msg);
-  return ERR_OK;
-}
-
-void
-tcpip_apimsg(struct api_msg *apimsg)
-{
-  struct tcpip_msg *msg;
-  msg = memp_malloc(MEMP_TCPIP_MSG);
-  if (msg == NULL) {
-    memp_free(MEMP_API_MSG, apimsg);
-    return;
-  }
-  msg->type = TCPIP_MSG_API;
-  msg->msg.apimsg = apimsg;
-  sys_mbox_post(mbox, msg);
-}
-
-void
-tcpip_init(void (* initfunc)(void *), void *arg)
-{
-  tcpip_init_done = initfunc;
-  tcpip_init_done_arg = arg;
-  mbox = sys_mbox_new();
-  sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
-}
-
-
-
-
+/*

+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.

+ * All rights reserved. 

+ * 

+ * Redistribution and use in source and binary forms, with or without modification, 

+ * are permitted provided that the following conditions are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright notice,

+ *    this list of conditions and the following disclaimer.

+ * 2. Redistributions in binary form must reproduce the above copyright notice,

+ *    this list of conditions and the following disclaimer in the documentation

+ *    and/or other materials provided with the distribution.

+ * 3. The name of the author may not be used to endorse or promote products

+ *    derived from this software without specific prior written permission. 

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 

+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 

+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 

+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 

+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 

+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 

+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 

+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 

+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 

+ * OF SUCH DAMAGE.

+ *

+ * This file is part of the lwIP TCP/IP stack.

+ * 

+ * Author: Adam Dunkels <adam@sics.se>

+ *

+ */

+

+#include "lwip/opt.h"

+

+#include "lwip/sys.h"

+

+#include "lwip/memp.h"

+#include "lwip/pbuf.h"

+

+#include "lwip/ip.h"

+#include "lwip/ip_frag.h"

+#include "lwip/udp.h"

+#include "lwip/tcp.h"

+

+#include "lwip/tcpip.h"

+

+static void (* tcpip_init_done)(void *arg) = NULL;

+static void *tcpip_init_done_arg;

+static sys_mbox_t mbox;

+

+#if LWIP_TCP

+static int tcpip_tcp_timer_active = 0;

+

+static void

+tcpip_tcp_timer(void *arg)

+{

+  (void)arg;

+

+  /* call TCP timer handler */

+  tcp_tmr();

+  /* timer still needed? */

+  if (tcp_active_pcbs || tcp_tw_pcbs) {

+    /* restart timer */

+    sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);

+  } else {

+    /* disable timer */

+    tcpip_tcp_timer_active = 0;

+  }

+}

+

+#if !NO_SYS

+void

+tcp_timer_needed(void)

+{

+  /* timer is off but needed again? */

+  if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {

+    /* enable and start timer */

+    tcpip_tcp_timer_active = 1;

+    sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);

+  }

+}

+#endif /* !NO_SYS */

+#endif /* LWIP_TCP */

+

+#if IP_REASSEMBLY

+static void

+ip_timer(void *data)

+{

+  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));

+  ip_reass_tmr();

+  sys_timeout(1000, ip_timer, NULL);

+}

+#endif

+

+static void

+tcpip_thread(void *arg)

+{

+  struct tcpip_msg *msg;

+

+  (void)arg;

+

+  ip_init();

+#if LWIP_UDP  

+  udp_init();

+#endif

+#if LWIP_TCP

+  tcp_init();

+#endif

+#if IP_REASSEMBLY

+  sys_timeout(1000, ip_timer, NULL);

+#endif

+  if (tcpip_init_done != NULL) {

+    tcpip_init_done(tcpip_init_done_arg);

+  }

+

+  while (1) {                          /* MAIN Loop */

+    sys_mbox_fetch(mbox, (void *)&msg);

+    switch (msg->type) {

+    case TCPIP_MSG_API:

+      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));

+      api_msg_input(msg->msg.apimsg);

+      break;

+    case TCPIP_MSG_INPUT:

+      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg));

+      ip_input(msg->msg.inp.p, msg->msg.inp.netif);

+      break;

+    case TCPIP_MSG_CALLBACK:

+      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));

+      msg->msg.cb.f(msg->msg.cb.ctx);

+      break;

+    default:

+      break;

+    }

+    memp_free(MEMP_TCPIP_MSG, msg);

+  }

+}

+

+err_t

+tcpip_input(struct pbuf *p, struct netif *inp)

+{

+  struct tcpip_msg *msg;

+  

+  msg = memp_malloc(MEMP_TCPIP_MSG);

+  if (msg == NULL) {

+    pbuf_free(p);    

+    return ERR_MEM;  

+  }

+  

+  msg->type = TCPIP_MSG_INPUT;

+  msg->msg.inp.p = p;

+  msg->msg.inp.netif = inp;

+  sys_mbox_post(mbox, msg);

+  return ERR_OK;

+}

+

+err_t

+tcpip_callback(void (*f)(void *ctx), void *ctx)

+{

+  struct tcpip_msg *msg;

+  

+  msg = memp_malloc(MEMP_TCPIP_MSG);

+  if (msg == NULL) {

+    return ERR_MEM;  

+  }

+  

+  msg->type = TCPIP_MSG_CALLBACK;

+  msg->msg.cb.f = f;

+  msg->msg.cb.ctx = ctx;

+  sys_mbox_post(mbox, msg);

+  return ERR_OK;

+}

+

+void

+tcpip_apimsg(struct api_msg *apimsg)

+{

+  struct tcpip_msg *msg;

+  msg = memp_malloc(MEMP_TCPIP_MSG);

+  if (msg == NULL) {

+    memp_free(MEMP_API_MSG, apimsg);

+    return;

+  }

+  msg->type = TCPIP_MSG_API;

+  msg->msg.apimsg = apimsg;

+  sys_mbox_post(mbox, msg);

+}

+

+void

+tcpip_init(void (* initfunc)(void *), void *arg)

+{

+  tcpip_init_done = initfunc;

+  tcpip_init_done_arg = arg;

+  mbox = sys_mbox_new();

+  sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);

+}

+

+

+

+