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;