mbed OS5

Fork of UIPEthernet by Zoltan Hudak

Revision:
4:d774541a34da
Parent:
2:049ce85163c5
Child:
6:10e42359e217
--- a/UIPClient.cpp	Sat Dec 20 11:10:40 2014 +0000
+++ b/UIPClient.cpp	Sun Mar 08 20:26:56 2015 +0000
@@ -3,6 +3,8 @@
  Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
  All rights reserved.
 
+ Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com>
+
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
@@ -18,9 +20,10 @@
  */
 extern "C"
 {
-#include  "utility/uip-conf.h"
-#include  "utility/uip.h"
-#include  "utility/uip_arp.h"
+#include "utility/uip-conf.h"
+#include "utility/uip.h"
+#include "utility/uip_arp.h"
+#include "utility/millis.h"
 #include "string.h"
 }
 #include "UIPEthernet.h"
@@ -32,7 +35,7 @@
 #endif
 #define UIP_TCP_PHYH_LEN    UIP_LLH_LEN + UIP_IPTCPH_LEN
 
-uip_userdata_closed_t* UIPClient::  closed_conns[UIP_CONNS];
+uip_userdata_t UIPClient::  all_data[UIP_CONNS];
 
 /**
  * @brief
@@ -41,20 +44,7 @@
  * @retval
  */
 UIPClient::UIPClient(void) :
-    _uip_conn(NULL),
-    data(NULL) {
-    UIPEthernet.set_uip_callback(&UIPClient::uip_callback);
-}
-
-/**
- * @brief
- * @note
- * @param
- * @retval
- */
-UIPClient::UIPClient(struct uip_conn* conn) :
-    _uip_conn(conn),
-    data(conn ? (uip_userdata_t*)conn->appstate.user : NULL)
+    data(NULL)
 { }
 
 /**
@@ -63,9 +53,8 @@
  * @param
  * @retval
  */
-UIPClient::UIPClient(uip_userdata_closed_t* conn_data) :
-    _uip_conn(NULL),
-    data((uip_userdata_t*)conn_data)
+UIPClient::UIPClient(uip_userdata_t* conn_data) :
+    data(conn_data)
 { }
 
 /**
@@ -75,22 +64,36 @@
  * @retval
  */
 int UIPClient::connect(IPAddress ip, uint16_t port) {
+    stop();
+
     uip_ipaddr_t    ipaddr;
     uip_ip_addr(ipaddr, ip);
-    _uip_conn = uip_connect(&ipaddr, htons(port));
-    if(_uip_conn) {
-        while((_uip_conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
+
+    struct uip_conn*    conn = uip_connect(&ipaddr, htons(port));
+    if(conn)
+    {
+#if UIP_CONNECT_TIMEOUT > 0
+        int32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT;
+#endif
+        while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
             UIPEthernet.tick();
-            if((_uip_conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
-            {
+            if((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
+                data = (uip_userdata_t*)conn->appstate;
 #ifdef UIPETHERNET_DEBUG_CLIENT
-                Serial.print("connected, state: ");
-                Serial.print(((uip_userdata_t*)_uip_conn->appstate.user)->state);
-                Serial.print(", first packet in: ");
-                Serial.println(((uip_userdata_t*)_uip_conn->appstate.user)->packets_in[0]);
+                Serial.print(F("connected, state: "));
+                Serial.print(data->state);
+                Serial.print(F(", first packet in: "));
+                Serial.println(data->packets_in[0]);
 #endif
                 return 1;
             }
+
+#if UIP_CONNECT_TIMEOUT > 0
+            if(((int32_t) (millis() - timeout)) > 0) {
+                conn->tcpstateflags = UIP_CLOSED;
+                break;
+            }
+#endif
         }
     }
 
@@ -111,7 +114,7 @@
     DNSClient   dns;
     IPAddress   remote_addr;
 
-    dns.begin(UIPEthernet.dnsServerIP());
+    dns.begin(UIPEthernetClass::_dnsServerAddress);
     ret = dns.getHostByName(host, remote_addr);
     if(ret == 1) {
         return connect(remote_addr, port);
@@ -127,29 +130,32 @@
  * @retval
  */
 void UIPClient::stop(void) {
-    if(data) {
+    if(data && data->state)
+    {
+#ifdef UIPETHERNET_DEBUG_CLIENT
+        Serial.println(F("before stop(), with data"));
+        _dumpAllData();
+#endif
         _flushBlocks(&data->packets_in[0]);
-        if(data->state & UIP_CLIENT_CLOSED) {
-            uip_userdata_closed_t **     cc = &UIPClient::closed_conns[0];
-            for(uint8_t i = 0; i < UIP_CONNS; i++) {
-                if(*cc == (void*)data) {
-                    *cc = NULL;
-                    break;
-                }
-
-                cc++;
-            }
-
-            free(data);
+        if(data->state & UIP_CLIENT_REMOTECLOSED) {
+            data->state = 0;
         }
         else {
             data->state |= UIP_CLIENT_CLOSE;
         }
 
-        data = NULL;
+#ifdef UIPETHERNET_DEBUG_CLIENT
+        Serial.println(F("after stop()"));
+        _dumpAllData();
+#endif
     }
 
-    _uip_conn = NULL;
+#ifdef UIPETHERNET_DEBUG_CLIENT
+    else {
+        Serial.println(F("stop(), data: NULL"));
+    }
+#endif
+    data = NULL;
     UIPEthernet.tick();
 }
 
@@ -160,7 +166,7 @@
  * @retval
  */
 uint8_t UIPClient::connected(void) {
-    return((_uip_conn && (_uip_conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) || available() > 0) ? 1 : 0;
+    return(data && (data->packets_in[0] != NOBLOCK || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
 }
 
 /**
@@ -170,7 +176,7 @@
  * @retval
  */
 bool UIPClient::operator==(const UIPClient& rhs) {
-    return _uip_conn && rhs._uip_conn && _uip_conn == rhs._uip_conn;
+    return data && rhs.data && (data == rhs.data);
 }
 
 /**
@@ -181,8 +187,7 @@
  */
 UIPClient::operator bool(void) {
     UIPEthernet.tick();
-    return(data || (_uip_conn && (data = (uip_userdata_t*)_uip_conn->appstate.user)))
-&&  (!(data->state & UIP_CLIENT_CLOSED) || data->packets_in[0] != NOBLOCK);
+    return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK);
 }
 
 /**
@@ -192,7 +197,7 @@
  * @retval
  */
 size_t UIPClient::write(uint8_t c) {
-    return _write(_uip_conn, &c, 1);
+    return _write(data, &c, 1);
 }
 
 /**
@@ -202,7 +207,7 @@
  * @retval
  */
 size_t UIPClient::write(const uint8_t* buf, size_t size) {
-    return _write(_uip_conn, buf, size);
+    return _write(data, buf, size);
 }
 
 /**
@@ -211,21 +216,20 @@
  * @param
  * @retval
  */
-size_t UIPClient::_write(struct uip_conn* conn, const uint8_t* buf, size_t size) {
-    uip_userdata_t*     u;
-    int                 remain = size;
-    uint16_t            written;
+size_t UIPClient::_write(uip_userdata_t* u, const uint8_t* buf, size_t size) {
+    int         remain = size;
+    uint16_t    written;
 #if UIP_ATTEMPTS_ON_WRITE > 0
-    uint16_t            attempts = UIP_ATTEMPTS_ON_WRITE;
+    uint16_t    attempts = UIP_ATTEMPTS_ON_WRITE;
 #endif
     repeat : UIPEthernet.tick();
-    if(conn && (u = (uip_userdata_t*)conn->appstate.user) && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) {
-        memhandle*  p = _currentBlock(&u->packets_out[0]);
-        if(*p == NOBLOCK)
+    if(u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) {
+        uint8_t p = _currentBlock(&u->packets_out[0]);
+        if(u->packets_out[p] == NOBLOCK)
         {
 newpacket:
-            *p = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN);
-            if(*p == NOBLOCK)
+            u->packets_out[p] = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN);
+            if(u->packets_out[p] == NOBLOCK)
             {
 #if UIP_ATTEMPTS_ON_WRITE > 0
                 if((--attempts) > 0)
@@ -240,23 +244,29 @@
         }
 
 #ifdef UIPETHERNET_DEBUG_CLIENT
-        Serial.print("UIPClient.write: writePacket(");
-        Serial.print(*p);
-        Serial.print(") pos: ");
+        Serial.print(F("UIPClient.write: writePacket("));
+        Serial.print(u->packets_out[p]);
+        Serial.print(F(") pos: "));
         Serial.print(u->out_pos);
-        Serial.print(", buf[");
+        Serial.print(F(", buf["));
         Serial.print(size - remain);
-        Serial.print("-");
+        Serial.print(F("-"));
         Serial.print(remain);
-        Serial.print("]: '");
+        Serial.print(F("]: '"));
         Serial.write((uint8_t*)buf + size - remain, remain);
-        Serial.println("'");
+        Serial.println(F("'"));
 #endif
-        written = UIPEthernet.network.writePacket(*p, u->out_pos, (uint8_t*)buf + size - remain, remain);
+        written = UIPEthernet.network.writePacket
+            (
+                u->packets_out[p],
+                u->out_pos,
+                (uint8_t*)buf + size - remain,
+                remain
+            );
         remain -= written;
         u->out_pos += written;
         if(remain > 0) {
-            if(p == &u->packets_out[UIP_SOCKET_NUMPACKETS - 1])
+            if(p == UIP_SOCKET_NUMPACKETS - 1)
             {
 #if UIP_ATTEMPTS_ON_WRITE > 0
                 if((--attempts) > 0)
@@ -272,6 +282,9 @@
         }
 
 ready:
+#if UIP_CLIENT_TIMER >= 0
+        u->timer = millis() + UIP_CLIENT_TIMER;
+#endif
         return size - remain;
     }
 
@@ -287,7 +300,7 @@
 int UIPClient::available(void) {
     if(*this)
         return _available(data);
-    return -1;
+    return 0;
 }
 
 /**
@@ -297,15 +310,9 @@
  * @retval
  */
 int UIPClient::_available(uip_userdata_t* u) {
-    memhandle*  p = &u->packets_in[0];
-    if(*p == NOBLOCK)
-        return 0;
-
     int len = 0;
-    for(memhandle * end = p + UIP_SOCKET_NUMPACKETS; p < end; p++) {
-        if(*p == NOBLOCK)
-            break;
-        len += UIPEthernet.network.blockSize(*p);
+    for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
+        len += UIPEthernet.network.blockSize(u->packets_in[i]);
     }
 
     return len;
@@ -319,25 +326,33 @@
  */
 int UIPClient::read(uint8_t* buf, size_t size) {
     if(*this) {
-        int         remain = size;
-        memhandle*  p = &data->packets_in[0];
-        if(*p == NOBLOCK)
+        uint16_t    remain = size;
+        if(data->packets_in[0] == NOBLOCK)
             return 0;
 
-        int read;
+        uint16_t    read;
         do
         {
-            read = UIPEthernet.network.readPacket(*p, 0, buf + size - remain, remain);
-            if(read == UIPEthernet.network.blockSize(*p)) {
+            read = UIPEthernet.network.readPacket(data->packets_in[0], 0, buf + size - remain, remain);
+            if(read == UIPEthernet.network.blockSize(data->packets_in[0])) {
                 remain -= read;
-                _eatBlock(p);
-                if(_uip_conn && uip_stopped(_uip_conn) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED)))
-                    data->state |= UIP_CLIENT_RESTART;
-                if(*p == NOBLOCK)
+                _eatBlock(&data->packets_in[0]);
+                if
+                (
+                    uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS])
+                &&  !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))
+                ) data->state |= UIP_CLIENT_RESTART;
+                if(data->packets_in[0] == NOBLOCK) {
+                    if(data->state & UIP_CLIENT_REMOTECLOSED) {
+                        data->state = 0;
+                        data = NULL;
+                    }
+
                     return size - remain;
+                }
             }
             else {
-                UIPEthernet.network.resizeBlock(*p, read);
+                UIPEthernet.network.resizeBlock(data->packets_in[0], read);
                 break;
             }
         } while(remain > 0);
@@ -368,10 +383,9 @@
  */
 int UIPClient::peek(void) {
     if(*this) {
-        memhandle   p = data->packets_in[0];
-        if(p != NOBLOCK) {
+        if(data->packets_in[0] != NOBLOCK) {
             uint8_t c;
-            UIPEthernet.network.readPacket(p, 0, &c, 1);
+            UIPEthernet.network.readPacket(data->packets_in[0], 0, &c, 1);
             return c;
         }
     }
@@ -397,67 +411,58 @@
  * @param
  * @retval
  */
-void UIPClient::uip_callback(uip_tcp_appstate_t* s) {
-    uip_userdata_t*     u = (uip_userdata_t*)s->user;
+void uipclient_appcall(void) {
+    uint16_t            send_len = 0;
+    uip_userdata_t*     u = (uip_userdata_t*)uip_conn->appstate;
     if(!u && uip_connected())
     {
 #ifdef UIPETHERNET_DEBUG_CLIENT
-        Serial.println("UIPClient uip_connected");
+        Serial.println(F("UIPClient uip_connected"));
+        UIPClient::_dumpAllData();
 #endif
-        // We want to store some data in our connections, so allocate some space
+        u = (uip_userdata_t*)UIPClient::_allocateData();
+        if(u) {
+            uip_conn->appstate = u;
+#ifdef UIPETHERNET_DEBUG_CLIENT
+            Serial.print(F("UIPClient allocated state: "));
+            Serial.println(u->state, BIN);
+#endif
+        }
 
-        // for it.  The connection_data struct is defined in a separate .h file,
-        // due to the way the Arduino IDE works.  (typedefs come after function
-        // definitions.)
-        u = (uip_userdata_t*)malloc(sizeof(uip_userdata_t));
-        if(u) {
-            memset(u, 0, sizeof(uip_userdata_t));
-            s->user = u;
-        }
+#ifdef UIPETHERNET_DEBUG_CLIENT
+        else
+            Serial.println(F("UIPClient allocation failed"));
+#endif
     }
 
     if(u) {
         if(uip_newdata())
         {
 #ifdef UIPETHERNET_DEBUG_CLIENT
-            Serial.print("UIPClient uip_newdata, uip_len:");
+            Serial.print(F("UIPClient uip_newdata, uip_len:"));
             Serial.println(uip_len);
 #endif
-            if(uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) {
-                memhandle   newPacket = UIPEthernet.network.allocBlock(uip_len);
-                if(newPacket != NOBLOCK) {
-                    memhandle*  p = _currentBlock(&u->packets_in[0]);
-                    //if it's not the first packet
-
-                    if(*p != NOBLOCK) {
-                        uint8_t slot = p - &u->packets_in[0];
-                        if(slot < UIP_SOCKET_NUMPACKETS - 1)
-                            p++;
-
-                        //if this is the last slot stop this connection
-                        if(slot >= UIP_SOCKET_NUMPACKETS - 2) {
-                            uip_stop();
-
-                            //if there's no free slot left omit loosing this packet and (again) stop this connection
-                            if(slot == UIP_SOCKET_NUMPACKETS - 1)
-                                goto reject_newdata;
+            if(uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) {
+                for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
+                    if(u->packets_in[i] == NOBLOCK) {
+                        u->packets_in[i] = UIPEthernet.network.allocBlock(uip_len);
+                        if(u->packets_in[i] != NOBLOCK) {
+                            UIPEthernet.network.copyPacket
+                                (
+                                    u->packets_in[i],
+                                    0,
+                                    UIPEthernetClass::in_packet,
+                                    ((uint8_t*)uip_appdata) - uip_buf,
+                                    uip_len
+                                );
+                            if(i == UIP_SOCKET_NUMPACKETS - 1)
+                                uip_stop();
+                            goto finish_newdata;
                         }
                     }
-
-                    UIPEthernet.network.copyPacket
-                        (
-                            newPacket,
-                            0,
-                            UIPEthernet.in_packet,
-                            ((uint8_t*)uip_appdata) - uip_buf,
-                            uip_len
-                        );
-                    *p = newPacket;
-                    goto finish_newdata;
                 }
 
-reject_newdata:
-                UIPEthernet.packetstate &= ~UIPETHERNET_FREEPACKET;
+                UIPEthernetClass::packetstate &= ~UIPETHERNET_FREEPACKET;
                 uip_stop();
             }
         }
@@ -472,66 +477,67 @@
         if(uip_closed() || uip_timedout())
         {
 #ifdef UIPETHERNET_DEBUG_CLIENT
-            Serial.println("UIPClient uip_closed");
+            Serial.println(F("UIPClient uip_closed"));
+            UIPClient::_dumpAllData();
 #endif
             // drop outgoing packets not sent yet:
 
-            _flushBlocks(&u->packets_out[0]);
+            UIPClient::_flushBlocks(&u->packets_out[0]);
             if(u->packets_in[0] != NOBLOCK) {
-                uip_userdata_closed_t **     closed_conn_data = &UIPClient::closed_conns[0];
-                for(uip_socket_ptr i = 0; i < UIP_CONNS; i++) {
-                    if(!*closed_conn_data) {
-                        *closed_conn_data = (uip_userdata_closed_t*)u;
-                        (*closed_conn_data)->lport = uip_conn->lport;
-                        break;
-                    }
-
-                    closed_conn_data++;
-                }
+                ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
+                u->state |= UIP_CLIENT_REMOTECLOSED;
             }
-
-            u->state |= UIP_CLIENT_CLOSED;
+            else
+                u->state = 0;
 
             // disassociate appdata.
-            s->user = NULL;
-            goto nodata;
+#ifdef UIPETHERNET_DEBUG_CLIENT
+            Serial.println(F("after UIPClient uip_closed"));
+            UIPClient::_dumpAllData();
+#endif
+            uip_conn->appstate = NULL;
+            goto finish;
         }
 
         if(uip_acked())
         {
 #ifdef UIPETHERNET_DEBUG_CLIENT
-            Serial.println("UIPClient uip_acked");
+            Serial.println(F("UIPClient uip_acked"));
 #endif
-            _eatBlock(&u->packets_out[0]);
+            UIPClient::_eatBlock(&u->packets_out[0]);
         }
 
         if(uip_poll() || uip_rexmit())
         {
 #ifdef UIPETHERNET_DEBUG_CLIENT
-            Serial.println("UIPClient uip_poll");
+            //Serial.println(F("UIPClient uip_poll"));
 #endif
-
-            memhandle   p = u->packets_out[0];
-            if(p != NOBLOCK) {
+            if(u->packets_out[0] != NOBLOCK) {
                 if(u->packets_out[1] == NOBLOCK) {
-                    uip_len = u->out_pos;
-                    if(uip_len > 0) {
-                        UIPEthernet.network.resizeBlock(p, 0, uip_len);
+                    send_len = u->out_pos;
+                    if(send_len > 0) {
+                        UIPEthernet.network.resizeBlock(u->packets_out[0], 0, send_len);
                     }
                 }
                 else
-                    uip_len = UIPEthernet.network.blockSize(p);
-                if(uip_len > 0) {
-                    UIPEthernet.uip_hdrlen = ((uint8_t*)uip_appdata) - uip_buf;
-                    UIPEthernet.uip_packet = UIPEthernet.network.allocBlock(UIPEthernet.uip_hdrlen + uip_len);
-                    if(UIPEthernet.uip_packet != NOBLOCK) {
-                        UIPEthernet.network.copyPacket(UIPEthernet.uip_packet, UIPEthernet.uip_hdrlen, p, 0, uip_len);
-                        UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET;
-                        uip_send(uip_appdata, uip_len);
+                    send_len = UIPEthernet.network.blockSize(u->packets_out[0]);
+                if(send_len > 0) {
+                    UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata) - uip_buf;
+                    UIPEthernetClass::uip_packet = UIPEthernet.network.allocBlock(UIPEthernetClass::uip_hdrlen + send_len);
+                    if(UIPEthernetClass::uip_packet != NOBLOCK) {
+                        UIPEthernet.network.copyPacket
+                            (
+                                UIPEthernetClass::uip_packet,
+                                UIPEthernetClass::uip_hdrlen,
+                                u->packets_out[0],
+                                0,
+                                send_len
+                            );
+                        UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET;
                     }
+                }
 
-                    return;
-                }
+                goto finish;
             }
         }
 
@@ -539,25 +545,30 @@
         if(u->state & UIP_CLIENT_CLOSE)
         {
 #ifdef UIPETHERNET_DEBUG_CLIENT
-            Serial.print("UIPClient state UIP_CLIENT_CLOSE");
-#endif
-            if(u->packets_out[0] == NOBLOCK)
-            {
-#ifdef UIPETHERNET_DEBUG_CLIENT
-                Serial.print("UIPClient state UIP_CLIENT_CLOSE -> free userdata");
+            Serial.println(F("UIPClient state UIP_CLIENT_CLOSE"));
+            UIPClient::_dumpAllData();
 #endif
-                free(u);
-                s->user = NULL;
+            if(u->packets_out[0] == NOBLOCK) {
+                u->state = 0;
+                uip_conn->appstate = NULL;
                 uip_close();
+#ifdef UIPETHERNET_DEBUG_CLIENT
+                Serial.println(F("no blocks out -> free userdata"));
+                UIPClient::_dumpAllData();
+#endif
             }
-            else
+            else {
                 uip_stop();
+#ifdef UIPETHERNET_DEBUG_CLIENT
+                Serial.println(F("blocks outstanding transfer -> uip_stop()"));
+#endif
+            }
         }
     }
 
-nodata:
-    UIPEthernet.uip_packet = NOBLOCK;
-    uip_len = 0;
+finish:
+    uip_send(uip_appdata, send_len);
+    uip_len = send_len;
 }
 
 /**
@@ -566,11 +577,32 @@
  * @param
  * @retval
  */
-memhandle* UIPClient::_currentBlock(memhandle* block) {
-    for(memhandle * end = block + UIP_SOCKET_NUMPACKETS - 1; block < end; block++)
-        if(*(block + 1) == NOBLOCK)
-            break;
-    return block;
+uip_userdata_t* UIPClient::_allocateData(void) {
+    for(uint8_t sock = 0; sock < UIP_CONNS; sock++) {
+        uip_userdata_t*     data = &UIPClient::all_data[sock];
+        if(!data->state) {
+            data->state = sock | UIP_CLIENT_CONNECTED;
+            memset(&data->packets_in[0], 0, sizeof(uip_userdata_t) - sizeof(data->state));
+            return data;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+uint8_t UIPClient::_currentBlock(memhandle* block) {
+    for(uint8_t i = 1; i < UIP_SOCKET_NUMPACKETS; i++) {
+        if(block[i] == NOBLOCK)
+            return i - 1;
+    }
+
+    return UIP_SOCKET_NUMPACKETS - 1;
 }
 
 /**
@@ -583,26 +615,26 @@
 {
 #ifdef UIPETHERNET_DEBUG_CLIENT
     memhandle*  start = block;
-    Serial.print("eatblock(");
+    Serial.print(F("eatblock("));
     Serial.print(*block);
-    Serial.print("): ");
+    Serial.print(F("): "));
     for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
         Serial.print(start[i]);
-        Serial.print(" ");
+        Serial.print(F(" "));
     }
 
-    Serial.print("-> ");
+    Serial.print(F("-> "));
 #endif
+    UIPEthernet.network.freeBlock(block[0]);
+    for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS - 1; i++) {
+        block[i] = block[i + 1];
+    }
 
-    memhandle*  end = block + (UIP_SOCKET_NUMPACKETS - 1);
-    UIPEthernet.network.freeBlock(*block);
-    while(block < end)
-        *block = *((block++) + 1);
-    *end = NOBLOCK;
+    block[UIP_SOCKET_NUMPACKETS - 1] = NOBLOCK;
 #ifdef UIPETHERNET_DEBUG_CLIENT
     for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
         Serial.print(start[i]);
-        Serial.print(" ");
+        Serial.print(F(" "));
     }
 
     Serial.println();
@@ -616,13 +648,48 @@
  * @retval
  */
 void UIPClient::_flushBlocks(memhandle* block) {
-    for(memhandle * end = block + UIP_SOCKET_NUMPACKETS; block < end; block++) {
-        if(*block != NOBLOCK) {
-            UIPEthernet.network.freeBlock(*block);
-            *block = NOBLOCK;
-        }
-        else
-            break;
+    for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
+        UIPEthernet.network.freeBlock(block[i]);
+        block[i] = NOBLOCK;
     }
 }
 
+#ifdef UIPETHERNET_DEBUG_CLIENT
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void UIPClient::_dumpAllData(void) {
+    for(uint8_t i = 0; i < UIP_CONNS; i++) {
+        Serial.print(F("UIPClient::all_data["));
+        Serial.print(i);
+        Serial.print(F("], state:"));
+        Serial.println(all_data[i].state, BIN);
+        Serial.print(F("packets_in: "));
+        for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) {
+            Serial.print(all_data[i].packets_in[j]);
+            Serial.print(F(" "));
+        }
+
+        Serial.println();
+        if(all_data[i].state & UIP_CLIENT_REMOTECLOSED) {
+            Serial.print(F("state remote closed, local port: "));
+            Serial.println(htons(((uip_userdata_closed_t *) (&all_data[i]))->lport));
+        }
+        else {
+            Serial.print(F("packets_out: "));
+            for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) {
+                Serial.print(all_data[i].packets_out[j]);
+                Serial.print(F(" "));
+            }
+
+            Serial.println();
+            Serial.print(F("out_pos: "));
+            Serial.println(all_data[i].out_pos);
+        }
+    }
+}
+#endif