cvs -q diff -wb -u -2 -p (in directory C:\OPENSOURCE\lwIP\lwip\)
Index: doc/rawapi.txt
===================================================================
RCS file: /sources/lwip/lwip/doc/rawapi.txt,v
retrieving revision 1.10
diff -w -b -u -2 -p -r1.10 rawapi.txt
--- doc/rawapi.txt	4 Jan 2008 22:18:27 -0000	1.10
+++ doc/rawapi.txt	13 Jan 2008 16:33:51 -0000
@@ -189,5 +189,7 @@ window.
   Sets the callback function that will be called when new data
   arrives. The callback function will be passed a NULL pbuf to
-  indicate that the remote host has closed the connection.
+  indicate that the remote host has closed the connection. The
+  callback function should delete the pbuf if it returns ERR_OK,
+  else, it should not delete (the core keep it).
 
 - void tcp_recved(struct tcp_pcb *pcb, u16_t len)


Index: src/api/api_msg.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/api_msg.c,v
retrieving revision 1.96
diff -w -b -u -2 -p -r1.96 api_msg.c
--- src/api/api_msg.c	12 Jan 2008 11:52:22 -0000	1.96
+++ src/api/api_msg.c	13 Jan 2008 16:28:08 -0000
@@ -166,5 +166,5 @@ recv_udp(void *arg, struct udp_pcb *pcb,
 /**
  * Receive callback function for TCP netconns.
- * Posts the packet to conn->recvmbox or deletes it on memory error.
+ * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
  *
  * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
@@ -183,5 +183,4 @@ recv_tcp(void *arg, struct tcp_pcb *pcb,
 
   if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
-    pbuf_free(p);
     return ERR_VAL;
   }
@@ -196,5 +195,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb,
   /* Register event with callback */
   API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
-  sys_mbox_post(conn->recvmbox, p);
+  if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
+    return ERR_MEM;
+  }
 
   return ERR_OK;


Index: src/core/tcp.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/tcp.c,v
retrieving revision 1.83
diff -w -b -u -2 -p -r1.83 tcp.c
--- src/core/tcp.c	12 Jan 2008 16:46:40 -0000	1.83
+++ src/core/tcp.c	13 Jan 2008 16:59:33 -0000
@@ -782,4 +782,15 @@ tcp_fasttmr(void)
   /* send delayed ACKs */  
   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+    /* If there is data which was previously "refused" by upper layer */
+    if (pcb->refused_data != NULL) {
+      /* Notify again application with data previously received. */
+      err_t err;
+      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n"));
+      TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
+      if (err == ERR_OK) {
+        pcb->refused_data = NULL;
+      }
+    }
+
     if (pcb->flags & TF_ACK_DELAY) {
       LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
@@ -1137,4 +1148,9 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
     LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
     
+    if (pcb->refused_data != NULL) {
+      LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n"));
+      pbuf_free(pcb->refused_data);
+      pcb->refused_data = NULL;
+    }
     if (pcb->unsent != NULL) {    
       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
@@ -1147,5 +1163,4 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
     }
-
     /* Stop the retransmission timer as it will expect data on unacked
        queue if it fires */


Index: src/core/tcp_in.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/tcp_in.c,v
retrieving revision 1.95
diff -w -b -u -2 -p -r1.95 tcp_in.c
--- src/core/tcp_in.c	4 Jan 2008 22:18:28 -0000	1.95
+++ src/core/tcp_in.c	13 Jan 2008 16:59:33 -0000
@@ -273,4 +273,21 @@ tcp_input(struct pbuf *p, struct netif *
     recv_flags = 0;
 
+    /* If there is data which was previously "refused" by upper layer */
+    if (pcb->refused_data != NULL) {
+      /* Notify again application with data previously received. */
+      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
+      TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
+      if (err == ERR_OK) {
+        pcb->refused_data = NULL;
+      } else {
+        /* drop incoming packets, because pcb is "full" */
+        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
+        TCP_STATS_INC(tcp.drop);
+        snmp_inc_tcpinerrs();
+        pbuf_free(p);
+        return;
+      }
+    }
+
     tcp_input_pcb = pcb;
     err = tcp_process(pcb);
@@ -307,4 +324,10 @@ tcp_input(struct pbuf *p, struct netif *
           /* Notify application that data has been received. */
           TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
+          
+          /* If the upper layer can't received this data, keep it */
+          if (err != ERR_OK) {
+            pcb->refused_data = recv_data;
+            LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
+          }
         }
       
@@ -314,4 +337,5 @@ tcp_input(struct pbuf *p, struct netif *
           TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
         }
+
         /* If there were no errors, we try to send something out. */
         if (err == ERR_OK) {


Index: src/include/lwip/tcp.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/tcp.h,v
retrieving revision 1.63
diff -w -b -u -2 -p -r1.63 tcp.h
--- src/include/lwip/tcp.h	4 Jan 2008 22:18:28 -0000	1.63
+++ src/include/lwip/tcp.h	13 Jan 2008 16:42:56 -0000
@@ -340,4 +340,6 @@ struct tcp_pcb {
 #endif /* TCP_QUEUE_OOSEQ */
 
+  struct pbuf *refused_data; /* Data previously received by not yet taken by upper layer */
+
 #if LWIP_CALLBACK_API
   /* Function to be called when more send buffer space is available.
@@ -472,4 +474,5 @@ err_t lwip_tcp_event(void *arg, struct t
                         if((pcb)->recv != NULL) \
                         { ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
+                          ret = ERR_OK; \
                           if (p) pbuf_free(p); }
 #define TCP_EVENT_CONNECTED(pcb,err,ret) \
