From 24b2b75f8c478562aef99fa0ceb1db6baf334f08 Mon Sep 17 00:00:00 2001
From: Stephan Linz <linz@li-pro.net>
Date: Sat, 23 Jan 2016 11:33:53 +0100
Subject: [PATCH] apps: tcpecho_raw: rename interface and symbols

Previously, from the API it was not apparent which type of echo
server will be used, in this case TCP echo on lwIP raw API. For
a proper generalization we want to see:

 - apps/tcpecho/tcpecho.c::tcpecho_init()
 - apps/tcpecho_raw/tcpecho_raw.c::tcpecho_raw_init()
 - apps/udpecho/udpecho.c::udpecho_init()

In future:

 - apps/udpecho_raw/udpecho_raw::udpecho_raw_init()

Signed-off-by: Stephan Linz <linz@li-pro.net>
---
 apps/tcpecho_raw/echo.c        | 362 -----------------------------------------
 apps/tcpecho_raw/echo.h        |  35 ----
 apps/tcpecho_raw/tcpecho_raw.c | 362 +++++++++++++++++++++++++++++++++++++++++
 apps/tcpecho_raw/tcpecho_raw.h |  35 ++++
 ports/Filelists.mk             |   2 +-
 ports/unix/proj/minimal/main.c |   4 +-
 ports/win32/test.c             |   4 +-
 7 files changed, 402 insertions(+), 402 deletions(-)
 delete mode 100644 apps/tcpecho_raw/echo.c
 delete mode 100644 apps/tcpecho_raw/echo.h
 create mode 100644 apps/tcpecho_raw/tcpecho_raw.c
 create mode 100644 apps/tcpecho_raw/tcpecho_raw.h

diff --git a/apps/tcpecho_raw/echo.c b/apps/tcpecho_raw/echo.c
deleted file mode 100644
index 2807246..0000000
--- a/apps/tcpecho_raw/echo.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * 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 and a contribution to the lwIP TCP/IP stack.
- *
- * Credits go to Adam Dunkels (and the current maintainers) of this software.
- *
- * Christiaan Simons rewrote this file to get a more stable echo example.
- */
-
-/**
- * @file
- * TCP echo server example using raw API.
- *
- * Echos all bytes sent by connecting client,
- * and passively closes when client is done.
- *
- */
-
-
-#include "lwip/opt.h"
-#include "lwip/debug.h"
-#include "lwip/stats.h"
-#include "lwip/tcp.h"
-#include "echo.h"
-
-#if LWIP_TCP
-
-static struct tcp_pcb *echo_pcb;
-
-enum echo_states
-{
-  ES_NONE = 0,
-  ES_ACCEPTED,
-  ES_RECEIVED,
-  ES_CLOSING
-};
-
-struct echo_state
-{
-  u8_t state;
-  u8_t retries;
-  struct tcp_pcb *pcb;
-  /* pbuf (chain) to recycle */
-  struct pbuf *p;
-};
-
-err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
-err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
-void echo_error(void *arg, err_t err);
-err_t echo_poll(void *arg, struct tcp_pcb *tpcb);
-err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
-void echo_send(struct tcp_pcb *tpcb, struct echo_state *es);
-void echo_close(struct tcp_pcb *tpcb, struct echo_state *es);
-void echo_free(struct echo_state *es);
-
-void
-echo_init(void)
-{
-  echo_pcb = tcp_new();
-  if (echo_pcb != NULL)
-  {
-    err_t err;
-
-    err = tcp_bind(echo_pcb, IP_ADDR_ANY, 7);
-    if (err == ERR_OK)
-    {
-      echo_pcb = tcp_listen(echo_pcb);
-      tcp_accept(echo_pcb, echo_accept);
-    }
-    else 
-    {
-      /* abort? output diagnostic? */
-    }
-  }
-  else
-  {
-    /* abort? output diagnostic? */
-  }
-}
-
-
-err_t
-echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
-{
-  err_t ret_err;
-  struct echo_state *es;
-
-  LWIP_UNUSED_ARG(arg);
-  LWIP_UNUSED_ARG(err);
-
-  /* Unless this pcb should have NORMAL priority, set its priority now.
-     When running out of pcbs, low priority pcbs can be aborted to create
-     new pcbs of higher priority. */
-  tcp_setprio(newpcb, TCP_PRIO_MIN);
-
-  es = (struct echo_state *)mem_malloc(sizeof(struct echo_state));
-  if (es != NULL)
-  {
-    es->state = ES_ACCEPTED;
-    es->pcb = newpcb;
-    es->retries = 0;
-    es->p = NULL;
-    /* pass newly allocated es to our callbacks */
-    tcp_arg(newpcb, es);
-    tcp_recv(newpcb, echo_recv);
-    tcp_err(newpcb, echo_error);
-    tcp_poll(newpcb, echo_poll, 0);
-    tcp_sent(newpcb, echo_sent);
-    ret_err = ERR_OK;
-  }
-  else
-  {
-    ret_err = ERR_MEM;
-  }
-  return ret_err;  
-}
-
-err_t
-echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
-{
-  struct echo_state *es;
-  err_t ret_err;
-
-  LWIP_ASSERT("arg != NULL",arg != NULL);
-  es = (struct echo_state *)arg;
-  if (p == NULL)
-  {
-    /* remote host closed connection */
-    es->state = ES_CLOSING;
-    if(es->p == NULL)
-    {
-       /* we're done sending, close it */
-       echo_close(tpcb, es);
-    }
-    else
-    {
-      /* we're not done yet */
-      echo_send(tpcb, es);
-    }
-    ret_err = ERR_OK;
-  }
-  else if(err != ERR_OK)
-  {
-    /* cleanup, for unkown reason */
-    if (p != NULL)
-    {
-      pbuf_free(p);
-    }
-    ret_err = err;
-  }
-  else if(es->state == ES_ACCEPTED)
-  {
-    /* first data chunk in p->payload */
-    es->state = ES_RECEIVED;
-    /* store reference to incoming pbuf (chain) */
-    es->p = p;
-    echo_send(tpcb, es);
-    ret_err = ERR_OK;
-  }
-  else if (es->state == ES_RECEIVED)
-  {
-    /* read some more data */
-    if(es->p == NULL)
-    {
-      es->p = p;
-      echo_send(tpcb, es);
-    }
-    else
-    {
-      struct pbuf *ptr;
-
-      /* chain pbufs to the end of what we recv'ed previously  */
-      ptr = es->p;
-      pbuf_cat(ptr,p);
-    }
-    ret_err = ERR_OK;
-  }
-  else if(es->state == ES_CLOSING)
-  {
-    /* odd case, remote side closing twice, trash data */
-    tcp_recved(tpcb, p->tot_len);
-    pbuf_free(p);
-    ret_err = ERR_OK;
-  }
-  else
-  {
-    /* unkown es->state, trash data  */
-    tcp_recved(tpcb, p->tot_len);
-    pbuf_free(p);
-    ret_err = ERR_OK;
-  }
-  return ret_err;
-}
-
-void
-echo_error(void *arg, err_t err)
-{
-  struct echo_state *es;
-
-  LWIP_UNUSED_ARG(err);
-
-  es = (struct echo_state *)arg;
-
-  echo_free(es);
-}
-
-err_t
-echo_poll(void *arg, struct tcp_pcb *tpcb)
-{
-  err_t ret_err;
-  struct echo_state *es;
-
-  es = (struct echo_state *)arg;
-  if (es != NULL)
-  {
-    if (es->p != NULL)
-    {
-      /* there is a remaining pbuf (chain)  */
-      echo_send(tpcb, es);
-    }
-    else
-    {
-      /* no remaining pbuf (chain)  */
-      if(es->state == ES_CLOSING)
-      {
-        echo_close(tpcb, es);
-      }
-    }
-    ret_err = ERR_OK;
-  }
-  else
-  {
-    /* nothing to be done */
-    tcp_abort(tpcb);
-    ret_err = ERR_ABRT;
-  }
-  return ret_err;
-}
-
-err_t
-echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
-{
-  struct echo_state *es;
-
-  LWIP_UNUSED_ARG(len);
-
-  es = (struct echo_state *)arg;
-  es->retries = 0;
-  
-  if(es->p != NULL)
-  {
-    /* still got pbufs to send */
-    tcp_sent(tpcb, echo_sent);
-    echo_send(tpcb, es);
-  }
-  else
-  {
-    /* no more pbufs to send */
-    if(es->state == ES_CLOSING)
-    {
-      echo_close(tpcb, es);
-    }
-  }
-  return ERR_OK;
-}
-
-void
-echo_send(struct tcp_pcb *tpcb, struct echo_state *es)
-{
-  struct pbuf *ptr;
-  err_t wr_err = ERR_OK;
- 
-  while ((wr_err == ERR_OK) &&
-         (es->p != NULL) && 
-         (es->p->len <= tcp_sndbuf(tpcb)))
-  {
-  ptr = es->p;
-
-  /* enqueue data for transmission */
-  wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
-  if (wr_err == ERR_OK)
-  {
-     u16_t plen;
-
-     plen = ptr->len;
-     /* continue with next pbuf in chain (if any) */
-     es->p = ptr->next;
-     if(es->p != NULL)
-     {
-       /* new reference! */
-       pbuf_ref(es->p);
-     }
-     /* chop first pbuf from chain */
-     pbuf_free(ptr);
-     /* we can read more data now */
-     tcp_recved(tpcb, plen);
-   }
-   else if(wr_err == ERR_MEM)
-   {
-      /* we are low on memory, try later / harder, defer to poll */
-     es->p = ptr;
-   }
-   else
-   {
-     /* other problem ?? */
-   }
-  }
-}
-
-void
-echo_close(struct tcp_pcb *tpcb, struct echo_state *es)
-{
-  tcp_arg(tpcb, NULL);
-  tcp_sent(tpcb, NULL);
-  tcp_recv(tpcb, NULL);
-  tcp_err(tpcb, NULL);
-  tcp_poll(tpcb, NULL, 0);
-
-  echo_free(es);
-
-  tcp_close(tpcb);
-}
-
-void echo_free(struct echo_state *es)
-{
-  if (es != NULL)
-  {
-    if (es->p)
-    {
-      /* free the buffer chain if present */
-      pbuf_free(es->p);
-    }
-
-    mem_free(es);
-  }  
-}
-
-#endif /* LWIP_TCP */
diff --git a/apps/tcpecho_raw/echo.h b/apps/tcpecho_raw/echo.h
deleted file mode 100644
index 8258fe7..0000000
--- a/apps/tcpecho_raw/echo.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- * 
- */
-#ifndef LWIP_ECHO_H
-#define LWIP_ECHO_H
-
-void echo_init(void);
-
-#endif /* LWIP_ECHO_H */
diff --git a/apps/tcpecho_raw/tcpecho_raw.c b/apps/tcpecho_raw/tcpecho_raw.c
new file mode 100644
index 0000000..69e9b56
--- /dev/null
+++ b/apps/tcpecho_raw/tcpecho_raw.c
@@ -0,0 +1,362 @@
+/*
+ * 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 and a contribution to the lwIP TCP/IP stack.
+ *
+ * Credits go to Adam Dunkels (and the current maintainers) of this software.
+ *
+ * Christiaan Simons rewrote this file to get a more stable echo example.
+ */
+
+/**
+ * @file
+ * TCP echo server example using raw API.
+ *
+ * Echos all bytes sent by connecting client,
+ * and passively closes when client is done.
+ *
+ */
+
+
+#include "lwip/opt.h"
+#include "lwip/debug.h"
+#include "lwip/stats.h"
+#include "lwip/tcp.h"
+#include "tcpecho_raw.h"
+
+#if LWIP_TCP
+
+static struct tcp_pcb *tcpecho_raw_pcb;
+
+enum tcpecho_raw_states
+{
+  ES_NONE = 0,
+  ES_ACCEPTED,
+  ES_RECEIVED,
+  ES_CLOSING
+};
+
+struct tcpecho_raw_state
+{
+  u8_t state;
+  u8_t retries;
+  struct tcp_pcb *pcb;
+  /* pbuf (chain) to recycle */
+  struct pbuf *p;
+};
+
+err_t tcpecho_raw_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
+err_t tcpecho_raw_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
+void tcpecho_raw_error(void *arg, err_t err);
+err_t tcpecho_raw_poll(void *arg, struct tcp_pcb *tpcb);
+err_t tcpecho_raw_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
+void tcpecho_raw_send(struct tcp_pcb *tpcb, struct tcpecho_raw_state *es);
+void tcpecho_raw_close(struct tcp_pcb *tpcb, struct tcpecho_raw_state *es);
+void tcpecho_raw_free(struct tcpecho_raw_state *es);
+
+void
+tcpecho_raw_init(void)
+{
+  tcpecho_raw_pcb = tcp_new();
+  if (tcpecho_raw_pcb != NULL)
+  {
+    err_t err;
+
+    err = tcp_bind(tcpecho_raw_pcb, IP_ADDR_ANY, 7);
+    if (err == ERR_OK)
+    {
+      tcpecho_raw_pcb = tcp_listen(tcpecho_raw_pcb);
+      tcp_accept(tcpecho_raw_pcb, tcpecho_raw_accept);
+    }
+    else 
+    {
+      /* abort? output diagnostic? */
+    }
+  }
+  else
+  {
+    /* abort? output diagnostic? */
+  }
+}
+
+
+err_t
+tcpecho_raw_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
+{
+  err_t ret_err;
+  struct tcpecho_raw_state *es;
+
+  LWIP_UNUSED_ARG(arg);
+  LWIP_UNUSED_ARG(err);
+
+  /* Unless this pcb should have NORMAL priority, set its priority now.
+     When running out of pcbs, low priority pcbs can be aborted to create
+     new pcbs of higher priority. */
+  tcp_setprio(newpcb, TCP_PRIO_MIN);
+
+  es = (struct tcpecho_raw_state *)mem_malloc(sizeof(struct tcpecho_raw_state));
+  if (es != NULL)
+  {
+    es->state = ES_ACCEPTED;
+    es->pcb = newpcb;
+    es->retries = 0;
+    es->p = NULL;
+    /* pass newly allocated es to our callbacks */
+    tcp_arg(newpcb, es);
+    tcp_recv(newpcb, tcpecho_raw_recv);
+    tcp_err(newpcb, tcpecho_raw_error);
+    tcp_poll(newpcb, tcpecho_raw_poll, 0);
+    tcp_sent(newpcb, tcpecho_raw_sent);
+    ret_err = ERR_OK;
+  }
+  else
+  {
+    ret_err = ERR_MEM;
+  }
+  return ret_err;  
+}
+
+err_t
+tcpecho_raw_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
+{
+  struct tcpecho_raw_state *es;
+  err_t ret_err;
+
+  LWIP_ASSERT("arg != NULL",arg != NULL);
+  es = (struct tcpecho_raw_state *)arg;
+  if (p == NULL)
+  {
+    /* remote host closed connection */
+    es->state = ES_CLOSING;
+    if(es->p == NULL)
+    {
+       /* we're done sending, close it */
+       tcpecho_raw_close(tpcb, es);
+    }
+    else
+    {
+      /* we're not done yet */
+      tcpecho_raw_send(tpcb, es);
+    }
+    ret_err = ERR_OK;
+  }
+  else if(err != ERR_OK)
+  {
+    /* cleanup, for unkown reason */
+    if (p != NULL)
+    {
+      pbuf_free(p);
+    }
+    ret_err = err;
+  }
+  else if(es->state == ES_ACCEPTED)
+  {
+    /* first data chunk in p->payload */
+    es->state = ES_RECEIVED;
+    /* store reference to incoming pbuf (chain) */
+    es->p = p;
+    tcpecho_raw_send(tpcb, es);
+    ret_err = ERR_OK;
+  }
+  else if (es->state == ES_RECEIVED)
+  {
+    /* read some more data */
+    if(es->p == NULL)
+    {
+      es->p = p;
+      tcpecho_raw_send(tpcb, es);
+    }
+    else
+    {
+      struct pbuf *ptr;
+
+      /* chain pbufs to the end of what we recv'ed previously  */
+      ptr = es->p;
+      pbuf_cat(ptr,p);
+    }
+    ret_err = ERR_OK;
+  }
+  else if(es->state == ES_CLOSING)
+  {
+    /* odd case, remote side closing twice, trash data */
+    tcp_recved(tpcb, p->tot_len);
+    pbuf_free(p);
+    ret_err = ERR_OK;
+  }
+  else
+  {
+    /* unkown es->state, trash data  */
+    tcp_recved(tpcb, p->tot_len);
+    pbuf_free(p);
+    ret_err = ERR_OK;
+  }
+  return ret_err;
+}
+
+void
+tcpecho_raw_error(void *arg, err_t err)
+{
+  struct tcpecho_raw_state *es;
+
+  LWIP_UNUSED_ARG(err);
+
+  es = (struct tcpecho_raw_state *)arg;
+
+  tcpecho_raw_free(es);
+}
+
+err_t
+tcpecho_raw_poll(void *arg, struct tcp_pcb *tpcb)
+{
+  err_t ret_err;
+  struct tcpecho_raw_state *es;
+
+  es = (struct tcpecho_raw_state *)arg;
+  if (es != NULL)
+  {
+    if (es->p != NULL)
+    {
+      /* there is a remaining pbuf (chain)  */
+      tcpecho_raw_send(tpcb, es);
+    }
+    else
+    {
+      /* no remaining pbuf (chain)  */
+      if(es->state == ES_CLOSING)
+      {
+        tcpecho_raw_close(tpcb, es);
+      }
+    }
+    ret_err = ERR_OK;
+  }
+  else
+  {
+    /* nothing to be done */
+    tcp_abort(tpcb);
+    ret_err = ERR_ABRT;
+  }
+  return ret_err;
+}
+
+err_t
+tcpecho_raw_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
+{
+  struct tcpecho_raw_state *es;
+
+  LWIP_UNUSED_ARG(len);
+
+  es = (struct tcpecho_raw_state *)arg;
+  es->retries = 0;
+  
+  if(es->p != NULL)
+  {
+    /* still got pbufs to send */
+    tcp_sent(tpcb, tcpecho_raw_sent);
+    tcpecho_raw_send(tpcb, es);
+  }
+  else
+  {
+    /* no more pbufs to send */
+    if(es->state == ES_CLOSING)
+    {
+      tcpecho_raw_close(tpcb, es);
+    }
+  }
+  return ERR_OK;
+}
+
+void
+tcpecho_raw_send(struct tcp_pcb *tpcb, struct tcpecho_raw_state *es)
+{
+  struct pbuf *ptr;
+  err_t wr_err = ERR_OK;
+ 
+  while ((wr_err == ERR_OK) &&
+         (es->p != NULL) && 
+         (es->p->len <= tcp_sndbuf(tpcb)))
+  {
+  ptr = es->p;
+
+  /* enqueue data for transmission */
+  wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
+  if (wr_err == ERR_OK)
+  {
+     u16_t plen;
+
+     plen = ptr->len;
+     /* continue with next pbuf in chain (if any) */
+     es->p = ptr->next;
+     if(es->p != NULL)
+     {
+       /* new reference! */
+       pbuf_ref(es->p);
+     }
+     /* chop first pbuf from chain */
+     pbuf_free(ptr);
+     /* we can read more data now */
+     tcp_recved(tpcb, plen);
+   }
+   else if(wr_err == ERR_MEM)
+   {
+      /* we are low on memory, try later / harder, defer to poll */
+     es->p = ptr;
+   }
+   else
+   {
+     /* other problem ?? */
+   }
+  }
+}
+
+void
+tcpecho_raw_close(struct tcp_pcb *tpcb, struct tcpecho_raw_state *es)
+{
+  tcp_arg(tpcb, NULL);
+  tcp_sent(tpcb, NULL);
+  tcp_recv(tpcb, NULL);
+  tcp_err(tpcb, NULL);
+  tcp_poll(tpcb, NULL, 0);
+
+  tcpecho_raw_free(es);
+
+  tcp_close(tpcb);
+}
+
+void tcpecho_raw_free(struct tcpecho_raw_state *es)
+{
+  if (es != NULL)
+  {
+    if (es->p)
+    {
+      /* free the buffer chain if present */
+      pbuf_free(es->p);
+    }
+
+    mem_free(es);
+  }  
+}
+
+#endif /* LWIP_TCP */
diff --git a/apps/tcpecho_raw/tcpecho_raw.h b/apps/tcpecho_raw/tcpecho_raw.h
new file mode 100644
index 0000000..b091ea7
--- /dev/null
+++ b/apps/tcpecho_raw/tcpecho_raw.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ * 
+ */
+#ifndef LWIP_TCPECHO_RAW_H
+#define LWIP_TCPECHO_RAW_H
+
+void tcpecho_raw_init(void);
+
+#endif /* LWIP_TCPECHO_RAW_H */
diff --git a/ports/Filelists.mk b/ports/Filelists.mk
index f5e91e4..52cdcb9 100644
--- a/ports/Filelists.mk
+++ b/ports/Filelists.mk
@@ -34,7 +34,7 @@ CONTRIBAPPFILES=$(CONTRIBDIR)/apps/httpserver/httpserver-netconn.c \
 	$(CONTRIBDIR)/apps/udpecho/udpecho.c \
 	$(CONTRIBDIR)/apps/tcpecho/tcpecho.c \
 	$(CONTRIBDIR)/apps/shell/shell.c \
-	$(CONTRIBDIR)/apps/tcpecho_raw/echo.c \
+	$(CONTRIBDIR)/apps/tcpecho_raw/tcpecho_raw.c \
 	$(CONTRIBDIR)/apps/netio/netio.c \
 	$(CONTRIBDIR)/apps/ping/ping.c \
 	$(CONTRIBDIR)/apps/shell/shell.c \
diff --git a/ports/unix/proj/minimal/main.c b/ports/unix/proj/minimal/main.c
index 3e20977..aa59916 100644
--- a/ports/unix/proj/minimal/main.c
+++ b/ports/unix/proj/minimal/main.c
@@ -55,7 +55,7 @@
 #include "lwip/apps/snmp_mib2.h"
 
 #include "apps/snmp_private_mib/private_mib.h"
-#include "apps/tcpecho_raw/echo.h"
+#include "apps/tcpecho_raw/tcpecho_raw.h"
 
 /* (manual) host IP configuration */
 static ip4_addr_t ipaddr, netmask, gw;
@@ -205,7 +205,7 @@ main(int argc, char **argv)
   snmp_init();
 #endif /* LWIP_SNMP */
 
-  echo_init();
+  tcpecho_raw_init();
 
   printf("Applications started.\n");
     
diff --git a/ports/win32/test.c b/ports/win32/test.c
index ed25d79..73669fa 100644
--- a/ports/win32/test.c
+++ b/ports/win32/test.c
@@ -72,7 +72,7 @@
 #include "apps/shell/shell.h"
 #include "apps/tcpecho/tcpecho.h"
 #include "apps/udpecho/udpecho.h"
-#include "apps/tcpecho_raw/echo.h"
+#include "apps/tcpecho_raw/tcpecho_raw.h"
 #include "apps/socket_examples/socket_examples.h"
 
 #if NO_SYS
@@ -563,7 +563,7 @@ apps_init(void)
 #if LWIP_NETCONN && defined(LWIP_TCPECHO_APP_NETCONN)
   tcpecho_init();
 #else /* LWIP_NETCONN && defined(LWIP_TCPECHO_APP_NETCONN) */
-  echo_init();
+  tcpecho_raw_init();
 #endif
 #endif /* LWIP_TCPECHO_APP && LWIP_NETCONN */
 #if LWIP_UDPECHO_APP && LWIP_NETCONN
-- 
2.7.0

