From 6833d8278935b54fd9a076421a6bec462d314c17 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Mon, 26 Oct 2020 12:59:40 +0000 Subject: [PATCH 1/7] Buffer overflow resilience And diag output of replies --- RingStream.cpp | 25 +++++++++++++++++++++++-- RingStream.h | 4 ++++ WifiInboundHandler.cpp | 25 +++++++++++++++++++++---- WifiInboundHandler.h | 5 +++-- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/RingStream.cpp b/RingStream.cpp index eee0753..cea17fb 100644 --- a/RingStream.cpp +++ b/RingStream.cpp @@ -28,11 +28,12 @@ RingStream::RingStream( const uint16_t len) _pos_read=0; _buffer[0]=0; _overflow=false; + _mark=0; } -size_t RingStream::write(uint8_t byte) { +size_t RingStream::write(uint8_t b) { if (_overflow) return 0; - _buffer[_pos_write] = byte; + _buffer[_pos_write] = b; ++_pos_write; if (_pos_write>=_len) _pos_write=0; if (_pos_write==_pos_read) { @@ -63,3 +64,23 @@ int RingStream::count() { } return counter; } + +int RingStream::freeSpace() { + if (_pos_read>_pos_write) return _pos_read-_pos_write-2; + else return _len - _pos_write + _pos_read-2; +} + + +void RingStream::mark() { + _mark=_pos_write; +} + +bool RingStream::commit() { + if (_overflow) { + _pos_write=_mark; + _overflow=false; + return false; // commit failed + } + write((uint8_t)0); + return true; // commit worked +} diff --git a/RingStream.h b/RingStream.h index 7a129e0..52caf9e 100644 --- a/RingStream.h +++ b/RingStream.h @@ -30,12 +30,16 @@ class RingStream : public Print { using Print::write; int read(); int count(); + int freeSpace(); + void mark(); + bool commit(); private: int _len; int _pos_write; int _pos_read; bool _overflow; + int _mark; byte * _buffer; }; diff --git a/WifiInboundHandler.cpp b/WifiInboundHandler.cpp index 8a779ee..6aa8738 100644 --- a/WifiInboundHandler.cpp +++ b/WifiInboundHandler.cpp @@ -65,9 +65,12 @@ void WifiInboundHandler::loop1() { cmd[count]=0; if (Diag::WIFI) DIAG(F("%e\n"),cmd); + outboundRing->mark(); // remember start of outbound data outboundRing->print(clientId); CommandDistributor::parse(clientId,cmd,outboundRing); - outboundRing->write((byte)0); + // The commit call will either write the null byte at the end of the output, + // OR rollback to the mark because the commend generated more than fits rthe buffer + outboundRing->commit(); return; } } @@ -95,8 +98,11 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { } if (ch=='>') { - if (Diag::WIFI) DIAG(F("[[XMIT %d]]"),currentReplySize); - for (int i=0;iwrite(outboundRing->read()); + for (int i=0;iread(); + wifiStream->write(cout); + if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise + } outboundRing->read(); // drop the end marker clientPendingCIPSEND=-1; pendingCipsend=false; @@ -159,6 +165,12 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { break; } if (Diag::WIFI) DIAG(F("\nWifi inbound data(%d:%d):"),runningClientId,dataLength); + if (inboundRing->freeSpace()<=(dataLength+1)) { + // This input would overflow the inbound ring, ignore it + loopState=IPD_IGNORE_DATA; + break; + } + inboundRing->mark(); inboundRing->print(runningClientId); // prefix inbound with client id loopState=IPD_DATA; break; @@ -170,11 +182,16 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { inboundRing->write(ch); dataLength--; if (dataLength == 0) { - inboundRing->write((byte)0); + inboundRing->commit(); loopState = ANYTHING; } break; + case IPD_IGNORE_DATA: // ignoring data that would not fit in inbound ring + dataLength--; + if (dataLength == 0) loopState = ANYTHING; + break; + case GOT_CLIENT_ID: // got x before CLOSE or CONNECTED loopState=(ch==',') ? GOT_CLIENT_ID2: SKIPTOEND; break; diff --git a/WifiInboundHandler.h b/WifiInboundHandler.h index fa41aa4..e947bdb 100644 --- a/WifiInboundHandler.h +++ b/WifiInboundHandler.h @@ -32,6 +32,7 @@ class WifiInboundHandler { IPD5, // got +IPD,c IPD6_LENGTH, // got +IPD,c, reading length IPD_DATA, // got +IPD,c,ll,: collecting data + IPD_IGNORE_DATA, // got +IPD,c,ll,: ignoring the data that won't fit inblound Ring GOT_CLIENT_ID, // clientid prefix to CONNECTED / CLOSED GOT_CLIENT_ID2, // clientid prefix to CONNECTED / CLOSED @@ -44,8 +45,8 @@ class WifiInboundHandler { INBOUND_STATE loop2(); Stream * wifiStream; - static const int INBOUND_RING = 200; - static const int OUTBOUND_RING = 1024; + static const int INBOUND_RING = 512; + static const int OUTBOUND_RING = 2048; RingStream * inboundRing; RingStream * outboundRing; From 8ff947f895dbe25fc5cffe47fdc8c60335b2aec2 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Mon, 26 Oct 2020 13:31:51 +0000 Subject: [PATCH 2/7] Passing outbound Ring to Withrottle This will allow Withrottle to send to other clients and broadcast messages. --- CommandDistributor.cpp | 2 +- CommandDistributor.h | 3 ++- WiThrottle.cpp | 12 ++++++++++-- WiThrottle.h | 5 +++-- WifiInboundHandler.cpp | 2 ++ WifiInboundHandler.h | 1 + WifiInterface.cpp | 3 +-- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 4d13f40..4496692 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -22,7 +22,7 @@ DCCEXParser * CommandDistributor::parser=0; -void CommandDistributor::parse(byte clientId,byte * buffer, Print * streamer) { +void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * streamer) { if (buffer[0] == '<') { if (!parser) parser = new DCCEXParser(); parser->parse(streamer, buffer, true); // tell JMRI parser that ACKS are blocking because we can't handle the async diff --git a/CommandDistributor.h b/CommandDistributor.h index 2bec81b..155ada0 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -19,11 +19,12 @@ #ifndef CommandDistributor_h #define CommandDistributor_h #include "DCCEXParser.h" +#include "RingStream.h" class CommandDistributor { public : - static void parse(byte clientId,byte* buffer, Print * streamer); + static void parse(byte clientId,byte* buffer, RingStream * streamer); private: static DCCEXParser * parser; }; diff --git a/WiThrottle.cpp b/WiThrottle.cpp index ac503a0..95ea07e 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -99,7 +99,7 @@ WiThrottle::~WiThrottle() { } } -void WiThrottle::parse(Print & stream, byte * cmdx) { +void WiThrottle::parse(RingStream & stream, byte * cmdx) { byte * cmd=cmdx; @@ -334,10 +334,18 @@ int WiThrottle::WiTToDCCSpeed(int WiTSpeed) { return WiTSpeed + 1; //offset others by 1 } -void WiThrottle::loop() { +void WiThrottle::loop(RingStream & stream) { // for each WiThrottle, check the heartbeat for (WiThrottle* wt=firstThrottle; wt!=NULL ; wt=wt->nextThrottle) wt->checkHeartbeat(); + + // TODO... any broadcasts to be done + /* MUST follow this model in this loop. + * stream->mark(); + * send 1 digit client id, and any data + * stream->commit() + */ + } void WiThrottle::checkHeartbeat() { diff --git a/WiThrottle.h b/WiThrottle.h index c1b5bba..fe06cfe 100644 --- a/WiThrottle.h +++ b/WiThrottle.h @@ -19,6 +19,7 @@ #ifndef WiThrottle_h #define WiThrottle_h +#include "RingStream.h" struct MYLOCO { char throttle; //indicates which throttle letter on client, often '0','1' or '2' @@ -27,8 +28,8 @@ struct MYLOCO { class WiThrottle { public: - static void loop(); - void parse(Print & stream, byte * cmd); + static void loop(RingStream & stream); + void parse(RingStream & stream, byte * cmd); static WiThrottle* getThrottle( int wifiClient); static bool annotateLeftRight; private: diff --git a/WifiInboundHandler.cpp b/WifiInboundHandler.cpp index 6aa8738..a13e789 100644 --- a/WifiInboundHandler.cpp +++ b/WifiInboundHandler.cpp @@ -31,6 +31,8 @@ void WifiInboundHandler::loop1() { // First handle all inbound traffic events because they will block the sending if (loop2()!=INBOUND_IDLE) return; + WiThrottle::loop(outboundRing); + // if nothing is already CIPSEND pending, we can CIPSEND one reply if (clientPendingCIPSEND<0) { int next=outboundRing->read(); diff --git a/WifiInboundHandler.h b/WifiInboundHandler.h index e947bdb..953b08d 100644 --- a/WifiInboundHandler.h +++ b/WifiInboundHandler.h @@ -2,6 +2,7 @@ #define WifiInboundHandler_h #include "RingStream.h" +#include "WiThrottle.h" #include "DIAG.h" class WifiInboundHandler { diff --git a/WifiInterface.cpp b/WifiInterface.cpp index c751cab..74018b9 100644 --- a/WifiInterface.cpp +++ b/WifiInterface.cpp @@ -22,7 +22,7 @@ #include #include "DIAG.h" #include "StringFormatter.h" -#include "WiThrottle.h" + #include "WifiInboundHandler.h" const char PROGMEM READY_SEARCH[] = "\r\nready\r\n"; @@ -295,7 +295,6 @@ bool WifiInterface::checkForOK( const unsigned int timeout, const char * waitfor void WifiInterface::loop() { if (connected) { - WiThrottle::loop(); WifiInboundHandler::loop(); } } From b7fc055953adca899a3d4470b87785a1dc7d0511 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Mon, 26 Oct 2020 13:58:25 +0000 Subject: [PATCH 3/7] Passing Strteamer correctly Previous method copied entire buffer!!!! --- CommandDistributor.cpp | 2 +- WiThrottle.cpp | 9 +++++---- WiThrottle.h | 10 +++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 4496692..de4e8bf 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -27,5 +27,5 @@ void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream if (!parser) parser = new DCCEXParser(); parser->parse(streamer, buffer, true); // tell JMRI parser that ACKS are blocking because we can't handle the async } - else WiThrottle::getThrottle(clientId)->parse(*streamer, buffer); + else WiThrottle::getThrottle(clientId)->parse(streamer, buffer); } diff --git a/WiThrottle.cpp b/WiThrottle.cpp index 95ea07e..61f7f92 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -99,7 +99,7 @@ WiThrottle::~WiThrottle() { } } -void WiThrottle::parse(RingStream & stream, byte * cmdx) { +void WiThrottle::parse(RingStream * stream, byte * cmdx) { byte * cmd=cmdx; @@ -205,7 +205,7 @@ int WiThrottle::getLocoId(byte * cmd) { if (cmd[0]!='L' && cmd[0]!='S') return 0; // should not match any locos return getInt(cmd+1); } -void WiThrottle::multithrottle(Print & stream, byte * cmd){ +void WiThrottle::multithrottle(RingStream * stream, byte * cmd){ char throttleChar=cmd[1]; int locoid=getLocoId(cmd+3); // -1 for * byte * aval=cmd; @@ -256,7 +256,7 @@ void WiThrottle::multithrottle(Print & stream, byte * cmd){ } } -void WiThrottle::locoAction(Print & stream, byte* aval, char throttleChar, int cab){ +void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar, int cab){ // Note cab=-1 for all cabs in the consist called throttleChar. // DIAG(F("\nLoco Action aval=%c%c throttleChar=%c, cab=%d"), aval[0],aval[1],throttleChar, cab); switch (aval[0]) { @@ -334,12 +334,13 @@ int WiThrottle::WiTToDCCSpeed(int WiTSpeed) { return WiTSpeed + 1; //offset others by 1 } -void WiThrottle::loop(RingStream & stream) { +void WiThrottle::loop(RingStream * stream) { // for each WiThrottle, check the heartbeat for (WiThrottle* wt=firstThrottle; wt!=NULL ; wt=wt->nextThrottle) wt->checkHeartbeat(); // TODO... any broadcasts to be done + (void)stream; /* MUST follow this model in this loop. * stream->mark(); * send 1 digit client id, and any data diff --git a/WiThrottle.h b/WiThrottle.h index fe06cfe..161020d 100644 --- a/WiThrottle.h +++ b/WiThrottle.h @@ -28,8 +28,8 @@ struct MYLOCO { class WiThrottle { public: - static void loop(RingStream & stream); - void parse(RingStream & stream, byte * cmd); + static void loop(RingStream * stream); + void parse(RingStream * stream, byte * cmd); static WiThrottle* getThrottle( int wifiClient); static bool annotateLeftRight; private: @@ -57,9 +57,9 @@ class WiThrottle { bool lastPowerState; // last power state sent to this client int DCCToWiTSpeed(int DCCSpeed); int WiTToDCCSpeed(int WiTSpeed); - void multithrottle(Print & stream, byte * cmd); - void locoAction(Print & stream, byte* aval, char throttleChar, int cab); - void accessory(Print & stream, byte* cmd); + void multithrottle(RingStream * stream, byte * cmd); + void locoAction(RingStream * stream, byte* aval, char throttleChar, int cab); + void accessory(RingStream *, byte* cmd); void checkHeartbeat(); }; #endif From 6c0b5d82be8ebcd68e14e08be2fbc98b56b74ef5 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Tue, 27 Oct 2020 10:38:30 +0000 Subject: [PATCH 4/7] Ring count improvements Count is stashed at start of message so can be got without counting. Commit discards empty replies automatically. --- RingStream.cpp | 51 ++++++++++++++++++++++++++---------------- RingStream.h | 3 ++- WifiInboundHandler.cpp | 41 ++++++++++++++------------------- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/RingStream.cpp b/RingStream.cpp index cea17fb..911bb80 100644 --- a/RingStream.cpp +++ b/RingStream.cpp @@ -29,58 +29,71 @@ RingStream::RingStream( const uint16_t len) _buffer[0]=0; _overflow=false; _mark=0; + _count=0; } size_t RingStream::write(uint8_t b) { if (_overflow) return 0; _buffer[_pos_write] = b; ++_pos_write; - if (_pos_write>=_len) _pos_write=0; + if (_pos_write==_len) _pos_write=0; if (_pos_write==_pos_read) { _overflow=true; - DIAG(F("\nRingStream(%d) OVERFLOW %d %d \n"),_len, _pos_write, _pos_read); return 0; } + _count++; return 1; } int RingStream::read() { - if (_pos_read==_pos_write) return -1; + if ((_pos_read==_pos_write) && !_overflow) return -1; // empty byte b=_buffer[_pos_read]; _pos_read++; - if (_pos_read>=_len) _pos_read=0; + if (_pos_read==_len) _pos_read=0; _overflow=false; return b; } int RingStream::count() { - int peek=_pos_read; - int counter=0; - while(_buffer[peek]) { - counter++; - peek++; - if (peek >= _len) peek=0; - } - return counter; + return (read()<<8) | read(); } int RingStream::freeSpace() { - if (_pos_read>_pos_write) return _pos_read-_pos_write-2; - else return _len - _pos_write + _pos_read-2; + // allow space for client flag and length bytes + if (_pos_read>_pos_write) return _pos_read-_pos_write-3; + else return _len - _pos_write + _pos_read-3; } -void RingStream::mark() { +// mark start of message with client id (0...9) +void RingStream::mark(uint8_t b) { _mark=_pos_write; + write(b); // client id + write((uint8_t)0); // count MSB placemarker + write((uint8_t)0); // count LSB placemarker + _count=0; } bool RingStream::commit() { if (_overflow) { - _pos_write=_mark; - _overflow=false; - return false; // commit failed + DIAG(F("\nRingStream(%d) commit(%d) OVERFLOW\n"),_len, _count); + // just throw it away + _pos_write=_mark; + _overflow=false; + return false; // commit failed } - write((uint8_t)0); + if (_count==0) { + // ignore empty response + _pos_write=_mark; + return true; // true=commit ok + } + // Go back to the _mark and inject the count 1 byte later + _mark++; + if (_mark==_len) _mark=0; + _buffer[_mark]=highByte(_count); + _mark++; + if (_mark==_len) _mark=0; + _buffer[_mark]=lowByte(_count); return true; // commit worked } diff --git a/RingStream.h b/RingStream.h index 52caf9e..b32e062 100644 --- a/RingStream.h +++ b/RingStream.h @@ -31,7 +31,7 @@ class RingStream : public Print { int read(); int count(); int freeSpace(); - void mark(); + void mark(uint8_t b); bool commit(); private: @@ -40,6 +40,7 @@ class RingStream : public Print { int _pos_read; bool _overflow; int _mark; + int _count; byte * _buffer; }; diff --git a/WifiInboundHandler.cpp b/WifiInboundHandler.cpp index a13e789..81cb3b7 100644 --- a/WifiInboundHandler.cpp +++ b/WifiInboundHandler.cpp @@ -35,18 +35,13 @@ void WifiInboundHandler::loop1() { // if nothing is already CIPSEND pending, we can CIPSEND one reply if (clientPendingCIPSEND<0) { - int next=outboundRing->read(); - if (next>=0) { + clientPendingCIPSEND=outboundRing->read(); + if (clientPendingCIPSEND>=0) { currentReplySize=outboundRing->count(); - if (currentReplySize==0) { - outboundRing->read(); // drop end marker - } - else { - clientPendingCIPSEND=next-'0'; // convert back to int - pendingCipsend=true; - } + pendingCipsend=true; } - } + } + if (pendingCipsend) { if (Diag::WIFI) DIAG( F("\nWiFi: [[CIPSEND=%d,%d]]"), clientPendingCIPSEND, currentReplySize); @@ -57,21 +52,19 @@ void WifiInboundHandler::loop1() { // if something waiting to execute, we can call it - int next=inboundRing->read(); - if (next>0) { - int clientId=next-'0'; //convert char to int + int clientId=inboundRing->read(); + if (clientId>=0) { int count=inboundRing->count(); - if (Diag::WIFI) DIAG(F("\nExec waiting %d %d:"),clientId,count); + if (Diag::WIFI) DIAG(F("\nWifi EXEC: %d %d:"),clientId,count); byte cmd[count+1]; for (int i=0;iread(); cmd[count]=0; if (Diag::WIFI) DIAG(F("%e\n"),cmd); - outboundRing->mark(); // remember start of outbound data - outboundRing->print(clientId); + outboundRing->mark(clientId); // remember start of outbound data CommandDistributor::parse(clientId,cmd,outboundRing); - // The commit call will either write the null byte at the end of the output, - // OR rollback to the mark because the commend generated more than fits rthe buffer + // The commit call will either write the lenbgth bytes + // OR rollback to the mark because the reply is empty or commend generated more than fits the buffer outboundRing->commit(); return; } @@ -92,7 +85,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { } switch (loopState) { - case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED + case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED, ERROR if (ch == '+') { loopState = IPD; @@ -100,12 +93,12 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { } if (ch=='>') { + if (Diag::WIFI) DIAG(F("[XMIT %d]"),currentReplySize); for (int i=0;iread(); wifiStream->write(cout); if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise } - outboundRing->read(); // drop the end marker clientPendingCIPSEND=-1; pendingCipsend=false; loopState=SKIPTOEND; @@ -170,10 +163,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { if (inboundRing->freeSpace()<=(dataLength+1)) { // This input would overflow the inbound ring, ignore it loopState=IPD_IGNORE_DATA; + if (Diag::WIFI) DIAG(F("\nWifi OVERFLOW IGNORING:")); break; } - inboundRing->mark(); - inboundRing->print(runningClientId); // prefix inbound with client id + inboundRing->mark(runningClientId); loopState=IPD_DATA; break; } @@ -181,10 +174,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { break; case IPD_DATA: // reading data - inboundRing->write(ch); + inboundRing->write(ch); dataLength--; if (dataLength == 0) { - inboundRing->commit(); + inboundRing->commit(); loopState = ANYTHING; } break; From 138851f45f5edda7df1914a330313b18a9d56a7a Mon Sep 17 00:00:00 2001 From: Asbelos Date: Tue, 27 Oct 2020 11:04:51 +0000 Subject: [PATCH 5/7] Cleaner purge on ERROR --- WifiInboundHandler.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/WifiInboundHandler.cpp b/WifiInboundHandler.cpp index 81cb3b7..00a682f 100644 --- a/WifiInboundHandler.cpp +++ b/WifiInboundHandler.cpp @@ -85,7 +85,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { } switch (loopState) { - case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED, ERROR + case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED, ERROR, SEND OK if (ch == '+') { loopState = IPD; @@ -109,6 +109,11 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { loopState=SKIPTOEND; break; } + + if (ch=='S') { // SEND OK probably + loopState=SKIPTOEND; + break; + } if (ch=='b') { // This is a busy indicator... probabaly must restart a CIPSEND pendingCipsend=(clientPendingCIPSEND>=0); @@ -121,6 +126,18 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { loopState=GOT_CLIENT_ID; break; } + + if (ch=='E') { // ERROR + if (pendingCipsend) { + // A CIPSEND was errored... just toss it away + if (Diag::WIFI) DIAG(F("Wifi: drop previous CIPSEND\n")); + for (int i=0;i<=currentReplySize;i++) outboundRing->read(); + clientPendingCIPSEND=-1; + pendingCipsend=false; + } + loopState=SKIPTOEND; + break; + } break; @@ -200,7 +217,9 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { // CLOSE if (runningClientId==clientPendingCIPSEND) { // clear the outbound for this client - for (int i=0;i<=currentReplySize;i++) outboundRing->read(); + for (int i=0;i<=currentReplySize;i++) outboundRing->read(); + clientPendingCIPSEND=-1; + pendingCipsend=false; } } loopState=SKIPTOEND; From a65ca0b704cffb3564fbf17aabb82d623a37c761 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Tue, 27 Oct 2020 12:33:01 +0000 Subject: [PATCH 6/7] Cleaner purge after error or connect fail --- WifiInboundHandler.cpp | 38 +++++++++++++++++--------------------- WifiInboundHandler.h | 1 + 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/WifiInboundHandler.cpp b/WifiInboundHandler.cpp index 00a682f..2463921 100644 --- a/WifiInboundHandler.cpp +++ b/WifiInboundHandler.cpp @@ -127,13 +127,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { break; } - if (ch=='E') { // ERROR - if (pendingCipsend) { + if (ch=='E' || ch=='l') { // ERROR or "link is not valid" + if (clientPendingCIPSEND>=0) { // A CIPSEND was errored... just toss it away - if (Diag::WIFI) DIAG(F("Wifi: drop previous CIPSEND\n")); - for (int i=0;i<=currentReplySize;i++) outboundRing->read(); - clientPendingCIPSEND=-1; - pendingCipsend=false; + purgeCurrentCIPSEND(); } loopState=SKIPTOEND; break; @@ -208,22 +205,13 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { loopState=(ch==',') ? GOT_CLIENT_ID2: SKIPTOEND; break; - case GOT_CLIENT_ID2: // got "x," before CLOSE or CONNECTED - loopState=(ch=='C') ? GOT_CLIENT_ID3: SKIPTOEND; + case GOT_CLIENT_ID2: // got "x," + if (ch=='C') { + // got "x C" before CLOSE or CONNECTED, or CONNECT FAILED + if (runningClientId==clientPendingCIPSEND) purgeCurrentCIPSEND(); + } + loopState=SKIPTOEND; break; - - case GOT_CLIENT_ID3: // got "x C" before CLOSE or CONNECTED (which is ignored) - if(ch=='L') { - // CLOSE - if (runningClientId==clientPendingCIPSEND) { - // clear the outbound for this client - for (int i=0;i<=currentReplySize;i++) outboundRing->read(); - clientPendingCIPSEND=-1; - pendingCipsend=false; - } - } - loopState=SKIPTOEND; - break; case SKIPTOEND: // skipping for /n if (ch=='\n') loopState=ANYTHING; @@ -232,3 +220,11 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { } // available return (loopState==ANYTHING) ? INBOUND_IDLE: INBOUND_BUSY; } + +void WifiInboundHandler::purgeCurrentCIPSEND() { + // A CIPSEND was sent but errored... or the client closed just toss it away + if (Diag::WIFI) DIAG(F("Wifi: DROPPING CIPSEND=%d,%d\n"),clientPendingCIPSEND,currentReplySize); + for (int i=0;i<=currentReplySize;i++) outboundRing->read(); + pendingCipsend=false; + clientPendingCIPSEND=-1; +} diff --git a/WifiInboundHandler.h b/WifiInboundHandler.h index 953b08d..1979565 100644 --- a/WifiInboundHandler.h +++ b/WifiInboundHandler.h @@ -44,6 +44,7 @@ class WifiInboundHandler { WifiInboundHandler(Stream * ESStream); void loop1(); INBOUND_STATE loop2(); + void purgeCurrentCIPSEND(); Stream * wifiStream; static const int INBOUND_RING = 512; From 96fba12d59ccdebf531a8ff602e668e2b17d637f Mon Sep 17 00:00:00 2001 From: Asbelos Date: Tue, 27 Oct 2020 12:50:01 +0000 Subject: [PATCH 7/7] ONLY 1 Call to WifiInboundHandler::setup! Or it wastes 1.5kb each time! --- WifiInterface.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/WifiInterface.cpp b/WifiInterface.cpp index 74018b9..9e7e6ed 100644 --- a/WifiInterface.cpp +++ b/WifiInterface.cpp @@ -90,6 +90,11 @@ bool WifiInterface::setup(long serial_link_speed, } #endif +DCCEXParser::setAtCommandCallback(ATCommand); + +// CAUTION... ONLY CALL THIS ONCE +WifiInboundHandler::setup(wifiStream); + return wifiUp; } @@ -109,8 +114,6 @@ bool WifiInterface::setup(Stream & setupStream, const __FlashStringHelper* SSid checkForOK(200, OK_SEARCH, true); } - DCCEXParser::setAtCommandCallback(ATCommand); - WifiInboundHandler::setup(wifiStream); DIAG(F("\n++ Wifi Setup %S ++\n"), connected ? F("OK") : F("FAILED")); return connected;