Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve general TCP stability #3027

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions libraries/ESP8266WiFi/src/WiFiClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ extern "C"
#include "include/ClientContext.h"
#include "c_types.h"

char lwip_bufferize = 1;

uint16_t WiFiClient::_localPort = 0;

template<>
Expand Down Expand Up @@ -163,6 +165,10 @@ bool WiFiClient::getNoDelay() {
return _client->getNoDelay();
}

size_t WiFiClient::ESPWriteAvailable() {
return _client->writeAvailable();
}

size_t WiFiClient::write(uint8_t b)
{
return write(&b, 1);
Expand Down
4 changes: 4 additions & 0 deletions libraries/ESP8266WiFi/src/WiFiClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#define WIFICLIENT_MAX_PACKET_SIZE 1460

extern char lwip_bufferize;

class ClientContext;
class WiFiServer;

Expand Down Expand Up @@ -75,6 +77,8 @@ class WiFiClient : public Client, public SList<WiFiClient> {
void setNoDelay(bool nodelay);
static void setLocalPortStart(uint16_t port) { _localPort = port; }

size_t ESPWriteAvailable();

friend class WiFiServer;

using Print::write;
Expand Down
73 changes: 72 additions & 1 deletion libraries/ESP8266WiFi/src/include/ClientContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ typedef int32_t recv_ret_t;
#endif

#include "DataSource.h"
#include "cbuf.h"

extern char lwip_bufferize;

class ClientContext
{
Expand All @@ -49,6 +52,12 @@ class ClientContext
tcp_sent(pcb, &_s_sent);
tcp_err(pcb, &_s_error);
tcp_poll(pcb, &_s_poll, 1);

if(lwip_bufferize) {
/* cbuf impl. handles size-1 bytes at most,
we want the whole TCP_WND at least */
_rx_full_buf = new cbuf(TCP_WND + 1);
}
}

err_t abort()
Expand Down Expand Up @@ -89,6 +98,13 @@ class ClientContext

~ClientContext()
{
if(_rx_full_buf)
delete _rx_full_buf;
}

uint16_t writeAvailable ()
{
return _pcb? tcp_sndbuf(_pcb): 0;
}

ClientContext* next() const
Expand Down Expand Up @@ -192,6 +208,9 @@ class ClientContext

size_t getSize() const
{
if(_rx_full_buf) {
return _rx_full_buf->available();
}
if(!_rx_buf) {
return 0;
}
Expand All @@ -201,6 +220,15 @@ class ClientContext

char read()
{
if(_rx_full_buf) {
if(!_rx_full_buf->available())
return 0;
if(_pcb) {
tcp_recved(_pcb, 1);
}
return (char)_rx_full_buf->read();
}

if(!_rx_buf) {
return 0;
}
Expand All @@ -212,6 +240,15 @@ class ClientContext

size_t read(char* dst, size_t size)
{
if(_rx_full_buf) {
DEBUGV(":rdifb %d\r\n", size);
size_t size_read = _rx_full_buf->read(dst, size);
if(_pcb) {
tcp_recved(_pcb, size_read);
}
return size_read;
}

if(!_rx_buf) {
return 0;
}
Expand All @@ -236,6 +273,9 @@ class ClientContext

char peek()
{
if(_rx_full_buf) {
return _rx_full_buf->available()? (char)_rx_full_buf->peek(): 0;
}
if(!_rx_buf) {
return 0;
}
Expand All @@ -245,6 +285,10 @@ class ClientContext

size_t peekBytes(char *dst, size_t size)
{
if(_rx_full_buf) {
return _rx_full_buf->peek(dst, size);
}

if(!_rx_buf) {
return 0;
}
Expand All @@ -262,6 +306,13 @@ class ClientContext

void flush()
{
if(_rx_full_buf) {
if(_pcb) {
tcp_recved(_pcb, _rx_full_buf->available());
}
return _rx_full_buf->flush();
}

if(!_rx_buf) {
return;
}
Expand Down Expand Up @@ -353,6 +404,7 @@ class ClientContext
err_t err = tcp_write(_pcb, buf, next_chunk, TCP_WRITE_FLAG_COPY);
_datasource->release_buffer(buf, next_chunk);
if (err == ERR_OK) {
DEBUGV(":w %d\r\n", next_chunk);
_written += next_chunk;
did_write = true;
}
Expand Down Expand Up @@ -420,7 +472,24 @@ class ClientContext
return ERR_ABRT;
}

if(_rx_buf) {
if(_rx_full_buf) {
DEBUGV(":rfb0\r\n");
for (pbuf* p = pb; p; p = p->next) {
/* cbuf does not like null pointer and 0 size */
if(p->len) {
DEBUGV(":rfb %d, %d\r\n", _rx_full_buf->available(), p->len);
size_t test = _rx_full_buf->write((const char*)p->payload, p->len);
if(test != p->len) {
/* internal error, cbuf is supposed to contain all receivable data (TCP_WND) */
printf/*DEBUGV*/(":rfbe %d %d %d !IntErr!\r\n", test, p->len, _rx_full_buf->available());
pbuf_free(pb);
return ERR_ABRT;
}
}
}
pbuf_free(pb);
}
else if(_rx_buf) {
DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
pbuf_cat(_rx_buf, pb);
} else {
Expand Down Expand Up @@ -481,6 +550,8 @@ class ClientContext
int _refcnt;
ClientContext* _next;

cbuf* _rx_full_buf = nullptr;

DataSource* _datasource = nullptr;
size_t _written = 0;
size_t _write_chunk_size = 256;
Expand Down
21 changes: 21 additions & 0 deletions tools/sdk/lwip/src/LWIP-CHANGE-MSS
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh

set -e

mss=$1

[ -z "$mss" ] && { echo "syntax: $0 <mss> (try with 256)"; exit 1; }

[ -f ../include/lwipopts.h.orig ] || mv ../include/lwipopts.h ../include/lwipopts.h.orig

< ../include/lwipopts.h.orig \
> ../include/lwipopts.h \
sed "s,^[ \t]*#define[ \t]*TCP_MSS\(.*\)$,#define TCP_MSS $mss //\1,g"

make clean
make
for i in liblwip_gcc.a liblwip.a liblwip_536.a; do
test -f ../../lib/${i}.orig || mv ../../lib/${i} ../../lib/${i}.orig
done

ln -sf ../lwip/src/liblwip_src.a ../../lib/liblwip_gcc.a