diff -ru lwip/src/core/pbuf.c lwip.trunk/src/core/pbuf.c
--- lwip/src/core/pbuf.c	2007-09-10 20:25:15.000000000 +0200
+++ lwip.trunk/src/core/pbuf.c	2007-12-18 11:29:24.703125000 +0100
@@ -617,6 +642,38 @@
 }
 
 /**
+ * Split two pbufs (or pbuf chains) from each other.
+ * 
+ * The caller must keep references to head and tail.
+ *
+ * @param h head pbuf (chain)
+ * @param t tail pbuf (chain)
+ *
+ * The ->tot_len fields of all pbufs of the head chain are adjusted.
+ * The ->next field of the last pbuf of the head chain is adjusted.
+ *
+ */
+void
+pbuf_split(struct pbuf *h, struct pbuf *t)
+{
+  struct pbuf *p, *q;
+  q = NULL;
+
+  LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
+  if ((h == NULL) || (t == NULL)) return;
+
+  for (p = h; p != t && p != NULL; p = p->next);
+  
+  if (p == t) {
+    for (p = h; p != t; p = p->next) {
+      p->tot_len -= t->tot_len;
+      q = p;
+    }
+    q->next = NULL;
+  }
+}
+
+/**
  * Dechains the first pbuf from its succeeding pbufs in the chain.
  *
  * Makes p->tot_len field equal to p->len.
diff -ru lwip/src/core/tcp.c lwip.trunk/src/core/tcp.c
--- lwip/src/core/tcp.c	2007-09-08 01:02:00.000000000 +0200
+++ lwip.trunk/src/core/tcp.c	2007-12-18 11:29:25.234375000 +0100
@@ -56,6 +56,8 @@
 u32_t tcp_ticks;
 const u8_t tcp_backoff[13] =
     { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
+/* Also seen 1.5, 3, 6, 12, 25, 48, 60 */
+const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; /* Times per slowtmr hits */
 
 /* The TCP PCB lists. */
 
@@ -390,9 +392,14 @@
 {
   if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
     pcb->rcv_wnd = TCP_WND;
+    pcb->rcv_ann_wnd = TCP_WND;
   } else {
     pcb->rcv_wnd += len;
+    if (pcb->rcv_wnd >= pcb->mss) {
+      pcb->rcv_ann_wnd = pcb->rcv_wnd;
+    }
   }
+
   if (!(pcb->flags & TF_ACK_DELAY) &&
      !(pcb->flags & TF_ACK_NOW)) {
     /*
@@ -497,6 +504,7 @@
   pcb->lastack = iss - 1;
   pcb->snd_lbb = iss - 1;
   pcb->rcv_wnd = TCP_WND;
+  pcb->rcv_ann_wnd = TCP_WND;
   pcb->snd_wnd = TCP_WND;
   pcb->mss = TCP_MSS;
   pcb->cwnd = 1;
@@ -564,36 +572,56 @@
       ++pcb_remove;
       LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
     } else {
-      /* Increase the retransmission timer if it is running */
-      if(pcb->rtime >= 0)
-        ++pcb->rtime;
-
-      if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
-        /* Time for a retransmission. */
-        LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F" pcb->rto %"S16_F"\n",
-                                    pcb->rtime, pcb->rto));
-
-        /* Double retransmission time-out unless we are trying to
-         * connect to somebody (i.e., we are in SYN_SENT). */
-        if (pcb->state != SYN_SENT) {
-          pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
-        }
-
-        /* Reset the retransmission timer. */
-        pcb->rtime = 0;
-
-        /* Reduce congestion window and ssthresh. */
-        eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
-        pcb->ssthresh = eff_wnd >> 1;
-        if (pcb->ssthresh < pcb->mss) {
-          pcb->ssthresh = pcb->mss * 2;
+      if (pcb->persist_backoff > 0) {
+        /* If snd_wnd is zero, use persist timer to send 1 byte probes
+         * instead of using the standard retransmission mechanism. */
+        pcb->persist_cnt++;
+        if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) {
+          pcb->persist_cnt = 0;
+          if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
+            pcb->persist_backoff++;
+          }
+          pcb->persist_probe++;
+          if (pcb->unacked != NULL) {
+            /* XXX: can we really assume there's only the 1 byte probe
+             * in the unacked queue? */
+            tcp_rexmit(pcb);
+          } else {
+            tcp_output(pcb);
+          }
         }
-        pcb->cwnd = pcb->mss;
-        LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
-                                     pcb->cwnd, pcb->ssthresh));
+      } else {
+        /* Increase the retransmission timer if it is running */
+        if(pcb->rtime >= 0)
+          ++pcb->rtime;
+        if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
+
+          /* Time for a retransmission. */
+          LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F" pcb->rto %"S16_F"\n",
+            pcb->rtime, pcb->rto));
+
+          /* Double retransmission time-out unless we are trying to
+           * connect to somebody (i.e., we are in SYN_SENT). */
+          if (pcb->state != SYN_SENT) {
+            pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
+          }
+
+          /* Reset the retransmission timer. */
+          pcb->rtime = 0;
+
+          /* Reduce congestion window and ssthresh. */
+          eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
+          pcb->ssthresh = eff_wnd >> 1;
+          if (pcb->ssthresh < 2 * pcb->mss) {
+            pcb->ssthresh = pcb->mss * 2;
+          }
+          pcb->cwnd = pcb->mss;
+          LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
+                                  pcb->cwnd, pcb->ssthresh));
  
-        /* The following needs to be called AFTER cwnd is set to one mss - STJ */
-        tcp_rexmit_rto(pcb);
+          /* The following needs to be called AFTER cwnd is set to one mss - STJ */
+          tcp_rexmit_rto(pcb);
+        }
       }
     }
     /* Check if this PCB has stayed too long in FIN-WAIT-2 */
@@ -938,6 +966,7 @@
     pcb->snd_buf = TCP_SND_BUF;
     pcb->snd_queuelen = 0;
     pcb->rcv_wnd = TCP_WND;
+    pcb->rcv_ann_wnd = TCP_WND;
     pcb->tos = 0;
     pcb->ttl = TCP_TTL;
     pcb->mss = TCP_MSS;
diff -ru lwip/src/core/tcp_in.c lwip.trunk/src/core/tcp_in.c
--- lwip/src/core/tcp_in.c	2007-09-08 01:02:00.000000000 +0200
+++ lwip.trunk/src/core/tcp_in.c	2007-12-18 11:29:25.296875000 +0100
@@ -479,7 +484,7 @@
       /*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
           TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
       */
-      if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
+      if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
         acceptable = 1;
       }
     }
@@ -539,7 +544,7 @@
       /* Call the user specified function to call when sucessfully
        * connected. */
       TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
-      tcp_ack(pcb);
+      tcp_ack_now(pcb);
     }
     /* received ACK? possibly a half-open connection */
     else if (flags & TCP_ACK) {
@@ -689,6 +694,9 @@
       pcb->snd_wnd = tcphdr->wnd;
       pcb->snd_wl1 = seqno;
       pcb->snd_wl2 = ackno;
+      if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
+          pcb->persist_backoff = 0;
+      }
       LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
 #if TCP_WND_DEBUG
     } else {
@@ -990,7 +998,7 @@
        processed. */
     /*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
       TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
-    if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){
+    if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
       if (pcb->rcv_nxt == seqno) {
         accepted_inseq = 1; 
         /* The incoming segment is the next in sequence. We check if
@@ -1017,11 +1025,11 @@
 
         /* Update the receiver's (our) window. */
         if (pcb->rcv_wnd < tcplen) {
-          pcb->rcv_wnd = 0;
+          pcb->rcv_wnd = 0;          
         } else {
-          pcb->rcv_wnd -= tcplen;
+          pcb->rcv_wnd -= tcplen;          
         }
-
+        pcb->rcv_ann_wnd = pcb->rcv_wnd;
         /* If there is data in the segment, we make preparations to
            pass this up to the application. The ->recv_data variable
            is used for holding the pbuf that goes to the
@@ -1055,8 +1063,10 @@
           pcb->rcv_nxt += TCP_TCPLEN(cseg);
           if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
             pcb->rcv_wnd = 0;
+            pcb->rcv_ann_wnd = 0;
           } else {
             pcb->rcv_wnd -= TCP_TCPLEN(cseg);
+            pcb->rcv_ann_wnd -= TCP_TCPLEN(cseg);
           }
           if (cseg->p->tot_len > 0) {
             /* Chain this pbuf onto the pbuf that we will pass to
@@ -1214,7 +1224,7 @@
     } else {
       /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
         TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
-      if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
+      if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
         tcp_ack_now(pcb);
       }
     }
@@ -1223,7 +1233,8 @@
        fall out of the window are ACKed. */
     /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
       TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
-    if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
+    if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_ann_wnd-1) &&
+       !(pcb->snd_wnd == 0)) {
       tcp_ack_now(pcb);
     }
   }
diff -ru lwip/src/core/tcp_out.c lwip.trunk/src/core/tcp_out.c
--- lwip/src/core/tcp_out.c	2007-09-08 01:02:00.000000000 +0200
+++ lwip.trunk/src/core/tcp_out.c	2007-12-18 11:29:25.343750000 +0100
@@ -57,6 +57,7 @@
 
 /* Forward declarations.*/
 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
+static err_t tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t len);
 
 /**
  * Called by tcp_close() to send a segment including flags but not data.
@@ -451,7 +452,7 @@
     tcphdr->seqno = htonl(pcb->snd_nxt);
     tcphdr->ackno = htonl(pcb->rcv_nxt);
     TCPH_FLAGS_SET(tcphdr, TCP_ACK);
-    tcphdr->wnd = htons(pcb->rcv_wnd);
+    tcphdr->wnd = htons(pcb->rcv_ann_wnd);
     tcphdr->urgp = 0;
     TCPH_HDRLEN_SET(tcphdr, 5);
 
@@ -497,9 +498,32 @@
                             ntohl(seg->tcphdr->seqno), pcb->lastack));
   }
 #endif /* TCP_CWND_DEBUG */
+  /* If the next segment in the unsent queue doesn't fit into the sending window,
+   * then split it.
+   */
+  if (seg != NULL && ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd) {    
+    if (pcb->snd_wnd == 0) {
+      if (pcb->persist_backoff == 0) {          
+        /* prepare for persist timer */
+        if (tcp_split_unsent_seg(pcb, 1) == ERR_OK) {
+          /* delay 1 byte probe by starting the presist timer */
+          seg = pcb->unsent;
+          pcb->persist_cnt = 0;
+          pcb->persist_backoff = 1;
+          pcb->persist_probe = 0;
+        }
+      }
+    } else {
+      tcp_split_unsent_seg(pcb, wnd);
+      /* pcb->unsent is updated */
+      seg = pcb->unsent;
+    }
+  }
+
   /* data available and window allows it to be sent? */
   while (seg != NULL &&
-  ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
+  ((ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) ||
+  pcb->persist_probe)) {
 #if TCP_CWND_DEBUG
     LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
                             pcb->snd_wnd, pcb->cwnd, wnd,
@@ -508,7 +532,9 @@
                             ntohl(seg->tcphdr->seqno), pcb->lastack, i));
     ++i;
 #endif /* TCP_CWND_DEBUG */
-
+    if (pcb->persist_probe) {      
+      pcb->persist_probe = 0;
+    }
     pcb->unsent = seg->next;
 
     if (pcb->state != SYN_SENT) {
@@ -571,13 +597,7 @@
    wnd fields remain. */
   seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
 
-  /* silly window avoidance */
-  if (pcb->rcv_wnd < pcb->mss) {
-    seg->tcphdr->wnd = 0;
-  } else {
-    /* advertise our receive window size in this TCP segment */
-    seg->tcphdr->wnd = htons(pcb->rcv_wnd);
-  }
+  seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
 
   /* If we don't have a local IP address, we get one by
      calling ip_route(). */
@@ -799,7 +819,7 @@
    tcphdr->seqno = htonl(pcb->snd_nxt - 1);
    tcphdr->ackno = htonl(pcb->rcv_nxt);
    TCPH_FLAGS_SET(tcphdr, 0);
-   tcphdr->wnd = htons(pcb->rcv_wnd);
+   tcphdr->wnd = htons(pcb->rcv_ann_wnd);
    tcphdr->urgp = 0;
    TCPH_HDRLEN_SET(tcphdr, 5);
 
@@ -830,4 +850,189 @@
   LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
 }
 
+
+static err_t
+tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t len)
+{
+  struct tcp_seg *seg, *useg;
+  struct pbuf *p, *q, *before_p;
+  u8_t *ptr;
+  u16_t offset, shrink;
+  u8_t queuelen;
+  u8_t method = 0;
+
+  useg = pcb->unsent;
+  if (useg == NULL) {
+    return ERR_MEM;
+  }
+
+  if (len == 0 || useg->len <= len) {
+    return ERR_OK;
+  }
+
+  LWIP_ASSERT("len <= mss", len <= pcb->mss);
+  LWIP_ASSERT("pcb->unsent->len > 0", pcb->unsent->len > 0);
+
+  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: split_unsent_seg: %u\n", (unsigned int)pcb->snd_queuelen));
+
+  /* We should check that we don't exceed TCP_SND_QUEUELEN but we need
+   * to split this packet so we may actually exceed the max value by 
+   * one!
+   */
+  queuelen = pcb->snd_queuelen;
+
+  /* Allocate memory for tcp_seg, and fill in fields. */
+  seg = memp_malloc(MEMP_TCP_SEG);
+  if (seg == NULL) {
+    LWIP_DEBUGF(TCP_RESIZE_DEBUG | 2, ("tcp_split_unsent_seg: could not allocate memory for tcp_seg\n"));
+    goto memerr;
+  }
+  seg->p = NULL;
+
+  /* copy from volatile memory? */
+  if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM)) == NULL) {
+    LWIP_DEBUGF(TCP_RESIZE_DEBUG | 2, ("tcp_split_unsent_seg: could not allocate memory for pbuf copy size %u\n", len));
+    goto memerr;
+  }
+  ptr = (u8_t*) seg->p->payload;
+  /* Shrink original packet, this is somewhat messy.
+   * We know the first pbuf in chain contains the complete TCP
+   * header and eventually the start of the TCP data.
+   */
+  shrink = len;
+  
+  /* Find pbuf holding the first TCP data byte. Necessacy because this
+   * packet can have been split before and therefore only tcp headers 
+   * may be present int the first pbuf */
+  p = useg->p;
+  before_p = NULL;
+  while (!((u8_t*)useg->dataptr >= (u8_t*)p->payload && (u8_t*)useg->dataptr < ((u8_t*)p->payload + p->len))) {
+    before_p = p;
+    p = p->next;
+    LWIP_ASSERT("Chain contains data", p != NULL);
+  }
+  offset = (u8_t*)useg->dataptr - (u8_t*)p->payload;
+
+  while (p != NULL && shrink > 0) {
+    if (p->len == 0 || shrink >= p->len - offset) {
+      /* Remove pbuf, update related pbufs in chain */
+      if (offset > 0) {
+        /* Keep header in pbuf, this is the first pbuf in the segment */
+        LWIP_ASSERT("TCP header in first pbuf", before_p == NULL);
+        method |= 0x01;
+        q = p->next;
+        pbuf_split(useg->p, q);
+        MEMCPY(ptr, (u8_t*)p->payload + offset, p->len - offset);
+        ptr += p->len - offset;
+        shrink -= p->len - offset;
+        pbuf_realloc(p, offset); /* p now only contains headers */
+        LWIP_ASSERT("TCP data in next chain", q != NULL);
+        pbuf_cat(useg->p, q);
+        useg->dataptr = q->payload;
+        before_p = p;
+      } else {
+        /* Remove complete pbuf */
+        method |= 0x02;
+        LWIP_ASSERT("Don't remove TCP header in first pbuf", before_p != NULL);
+        pbuf_split(useg->p, p);
+        q = p->next;
+        pbuf_split(p, q);
+        MEMCPY(ptr, (u8_t*)p->payload, p->len);
+        ptr += p->len;
+        shrink -= p->len;
+        pbuf_free(p);
+        queuelen--;
+        LWIP_ASSERT("Don't remove all data", q != NULL);
+        pbuf_cat(useg->p, q);
+        useg->dataptr = q->payload;
+      }
+      p = q;
+      LWIP_ASSERT("No pbuf/data length mismatch", !(p == NULL && shrink > 0));
+    } else {
+      /* Resize pbuf */
+      method |= 0x04;
+      q = p->next;
+      pbuf_split(useg->p, q);
+      MEMCPY(ptr, (u8_t*)p->payload + offset, shrink);
+      ptr += shrink;
+      MEMCPY((u8_t*)p->payload + offset, (u8_t*)p->payload + offset + shrink, p->len - offset - shrink);
+      if (before_p != NULL) {
+        LWIP_ASSERT("before_p is updated", before_p->next == p);
+        pbuf_split(useg->p, p);
+      }
+      pbuf_realloc(p, p->len - shrink);
+      if (before_p != NULL) {
+        pbuf_cat(useg->p, p);
+      }
+      if (q != NULL) {
+        pbuf_cat(useg->p, q);
+      }
+      useg->dataptr = (u8_t*)p->payload + offset;
+      p = q;
+      shrink = 0;
+    }
+    offset = 0; /* Offset is in first pbuf so it's not relevant any more */
+  }
+  LWIP_ASSERT("All data removed from original pbuf", shrink == 0);
+  LWIP_ASSERT("All removed data copied to new segment", ptr == (u8_t*)seg->p->payload + len);
+
+  useg->len -= len;
+
+  seg->len = len;
+  seg->dataptr = seg->p->payload;
+  queuelen++;
+
+  /* build TCP header */
+  if (pbuf_header(seg->p, TCP_HLEN)) {
+    LWIP_DEBUGF(TCP_RESIZE_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
+    TCP_STATS_INC(tcp.err);
+    goto memerr;
+  }
+  seg->tcphdr = seg->p->payload;
+  seg->tcphdr->src = htons(pcb->local_port);
+  seg->tcphdr->dest = htons(pcb->remote_port);
+  seg->tcphdr->seqno = pcb->unsent->tcphdr->seqno;
+  seg->tcphdr->urgp = 0;
+  TCPH_FLAGS_SET(seg->tcphdr, 0);
+  /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
+
+  TCPH_HDRLEN_SET(seg->tcphdr, 5);
+
+  /* We don't have to touch pcb->snd_buf because the total amount of 
+   * data is constant when packet is split */
+
+  /* update number of segments on the queues. Note that length now may 
+   * exceed TCP_SND_QUEUELEN! */
+  pcb->snd_queuelen = queuelen;
+
+  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_split_unsent_seg: %d (after enqueued)\n", pcb->snd_queuelen));
+  if (pcb->snd_queuelen != 0) {
+    LWIP_ASSERT("tcp_split_unsent_seg: valid queue length",
+        pcb->unacked != NULL || pcb->unsent != NULL);
+  }
+
+  /* Set the PSH flag in the last segment that we enqueued, but only
+     if the segment has data (indicated by seglen > 0). */
+  if (seg->tcphdr != NULL) {
+    TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
+  }
+
+  /* Update original segment with a new sequence number */
+  pcb->unsent->tcphdr->seqno = htonl(ntohl(pcb->unsent->tcphdr->seqno) + len);
+
+  /* Finally insert new segment first in queue */
+  seg->next = pcb->unsent;
+  pcb->unsent = seg;
+
+  return ERR_OK;
+memerr:
+  TCP_STATS_INC(tcp.memerr);
+
+  if (pcb->snd_queuelen != 0) {
+    LWIP_ASSERT("tcp_split_unsent_seg: valid queue length", pcb->unacked != NULL ||
+        pcb->unsent != NULL);
+  }
+  LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_split_unsent_seg: %d (with mem err)\n", pcb->snd_queuelen));
+  return ERR_MEM;
+}
 #endif /* LWIP_TCP */
diff -ru lwip/src/include/lwip/opt.h lwip.trunk/src/include/lwip/opt.h
--- lwip/src/include/lwip/opt.h	2007-09-10 20:12:13.000000000 +0200
+++ lwip.trunk/src/include/lwip/opt.h	2007-12-18 11:29:26.687500000 +0100
@@ -1422,6 +1425,13 @@
 #endif
 
 /**
+ * TCP_RESIZE_DEBUG: Enable debugging for resizing of TCP packets in send queue.
+ */
+#ifndef TCP_RESIZE_DEBUG
+#define TCP_RESIZE_DEBUG                LWIP_DBG_OFF
+#endif
+
+/**
  * UDP_DEBUG: Enable debugging in UDP.
  */
 #ifndef UDP_DEBUG
diff -ru lwip/src/include/lwip/pbuf.h lwip.trunk/src/include/lwip/pbuf.h
--- lwip/src/include/lwip/pbuf.h	2007-09-08 01:02:03.000000000 +0200
+++ lwip.trunk/src/include/lwip/pbuf.h	2007-12-18 11:29:26.734375000 +0100
@@ -107,6 +110,7 @@
 u8_t pbuf_clen(struct pbuf *p);  
 void pbuf_cat(struct pbuf *h, struct pbuf *t);
 void pbuf_chain(struct pbuf *h, struct pbuf *t);
+void pbuf_split(struct pbuf *h, struct pbuf *t);
 struct pbuf *pbuf_dechain(struct pbuf *p);
 err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
 u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
diff -ru lwip/src/include/lwip/tcp.h lwip.trunk/src/include/lwip/tcp.h
--- lwip/src/include/lwip/tcp.h	2007-09-13 19:46:13.000000000 +0200
+++ lwip.trunk/src/include/lwip/tcp.h	2007-12-18 11:29:27.218750000 +0100
@@ -266,6 +266,7 @@
   /* receiver variables */
   u32_t rcv_nxt;   /* next seqno expected */
   u16_t rcv_wnd;   /* receiver window */
+  u16_t rcv_ann_wnd; /* the window announced to the other part */
   
   /* Timers */
   u32_t tmr;
@@ -378,6 +379,15 @@
   
   /* KEEPALIVE counter */
   u8_t keep_cnt_sent;
+
+  /* Persist timer back-off */
+  u8_t persist_backoff;
+
+  /* Persist timer send probe flag*/
+  u8_t persist_probe;
+
+  /* Persist timer counter */
+  u32_t persist_cnt;
 };
 
 struct tcp_pcb_listen {  
