1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-03-14 18:13:09 +01:00

Ring count improvements

Count is stashed at start of message so can be got without counting.
Commit discards empty replies automatically.
This commit is contained in:
Asbelos 2020-10-27 10:38:30 +00:00
parent b7fc055953
commit 6c0b5d82be
3 changed files with 51 additions and 44 deletions

View File

@ -29,58 +29,71 @@ RingStream::RingStream( const uint16_t len)
_buffer[0]=0; _buffer[0]=0;
_overflow=false; _overflow=false;
_mark=0; _mark=0;
_count=0;
} }
size_t RingStream::write(uint8_t b) { size_t RingStream::write(uint8_t b) {
if (_overflow) return 0; if (_overflow) return 0;
_buffer[_pos_write] = b; _buffer[_pos_write] = b;
++_pos_write; ++_pos_write;
if (_pos_write>=_len) _pos_write=0; if (_pos_write==_len) _pos_write=0;
if (_pos_write==_pos_read) { if (_pos_write==_pos_read) {
_overflow=true; _overflow=true;
DIAG(F("\nRingStream(%d) OVERFLOW %d %d \n"),_len, _pos_write, _pos_read);
return 0; return 0;
} }
_count++;
return 1; return 1;
} }
int RingStream::read() { int RingStream::read() {
if (_pos_read==_pos_write) return -1; if ((_pos_read==_pos_write) && !_overflow) return -1; // empty
byte b=_buffer[_pos_read]; byte b=_buffer[_pos_read];
_pos_read++; _pos_read++;
if (_pos_read>=_len) _pos_read=0; if (_pos_read==_len) _pos_read=0;
_overflow=false; _overflow=false;
return b; return b;
} }
int RingStream::count() { int RingStream::count() {
int peek=_pos_read; return (read()<<8) | read();
int counter=0;
while(_buffer[peek]) {
counter++;
peek++;
if (peek >= _len) peek=0;
}
return counter;
} }
int RingStream::freeSpace() { int RingStream::freeSpace() {
if (_pos_read>_pos_write) return _pos_read-_pos_write-2; // allow space for client flag and length bytes
else return _len - _pos_write + _pos_read-2; 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; _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() { bool RingStream::commit() {
if (_overflow) { if (_overflow) {
_pos_write=_mark; DIAG(F("\nRingStream(%d) commit(%d) OVERFLOW\n"),_len, _count);
_overflow=false; // just throw it away
return false; // commit failed _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 return true; // commit worked
} }

View File

@ -31,7 +31,7 @@ class RingStream : public Print {
int read(); int read();
int count(); int count();
int freeSpace(); int freeSpace();
void mark(); void mark(uint8_t b);
bool commit(); bool commit();
private: private:
@ -40,6 +40,7 @@ class RingStream : public Print {
int _pos_read; int _pos_read;
bool _overflow; bool _overflow;
int _mark; int _mark;
int _count;
byte * _buffer; byte * _buffer;
}; };

View File

@ -35,18 +35,13 @@ void WifiInboundHandler::loop1() {
// if nothing is already CIPSEND pending, we can CIPSEND one reply // if nothing is already CIPSEND pending, we can CIPSEND one reply
if (clientPendingCIPSEND<0) { if (clientPendingCIPSEND<0) {
int next=outboundRing->read(); clientPendingCIPSEND=outboundRing->read();
if (next>=0) { if (clientPendingCIPSEND>=0) {
currentReplySize=outboundRing->count(); currentReplySize=outboundRing->count();
if (currentReplySize==0) { pendingCipsend=true;
outboundRing->read(); // drop end marker
}
else {
clientPendingCIPSEND=next-'0'; // convert back to int
pendingCipsend=true;
}
} }
} }
if (pendingCipsend) { if (pendingCipsend) {
if (Diag::WIFI) DIAG( F("\nWiFi: [[CIPSEND=%d,%d]]"), clientPendingCIPSEND, currentReplySize); 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 // if something waiting to execute, we can call it
int next=inboundRing->read(); int clientId=inboundRing->read();
if (next>0) { if (clientId>=0) {
int clientId=next-'0'; //convert char to int
int count=inboundRing->count(); 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]; byte cmd[count+1];
for (int i=0;i<count;i++) cmd[i]=inboundRing->read(); for (int i=0;i<count;i++) cmd[i]=inboundRing->read();
cmd[count]=0; cmd[count]=0;
if (Diag::WIFI) DIAG(F("%e\n"),cmd); if (Diag::WIFI) DIAG(F("%e\n"),cmd);
outboundRing->mark(); // remember start of outbound data outboundRing->mark(clientId); // remember start of outbound data
outboundRing->print(clientId);
CommandDistributor::parse(clientId,cmd,outboundRing); CommandDistributor::parse(clientId,cmd,outboundRing);
// The commit call will either write the null byte at the end of the output, // The commit call will either write the lenbgth bytes
// OR rollback to the mark because the commend generated more than fits rthe buffer // OR rollback to the mark because the reply is empty or commend generated more than fits the buffer
outboundRing->commit(); outboundRing->commit();
return; return;
} }
@ -92,7 +85,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
} }
switch (loopState) { 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 == '+') { if (ch == '+') {
loopState = IPD; loopState = IPD;
@ -100,12 +93,12 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
} }
if (ch=='>') { if (ch=='>') {
if (Diag::WIFI) DIAG(F("[XMIT %d]"),currentReplySize);
for (int i=0;i<currentReplySize;i++) { for (int i=0;i<currentReplySize;i++) {
int cout=outboundRing->read(); int cout=outboundRing->read();
wifiStream->write(cout); wifiStream->write(cout);
if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise
} }
outboundRing->read(); // drop the end marker
clientPendingCIPSEND=-1; clientPendingCIPSEND=-1;
pendingCipsend=false; pendingCipsend=false;
loopState=SKIPTOEND; loopState=SKIPTOEND;
@ -170,10 +163,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
if (inboundRing->freeSpace()<=(dataLength+1)) { if (inboundRing->freeSpace()<=(dataLength+1)) {
// This input would overflow the inbound ring, ignore it // This input would overflow the inbound ring, ignore it
loopState=IPD_IGNORE_DATA; loopState=IPD_IGNORE_DATA;
if (Diag::WIFI) DIAG(F("\nWifi OVERFLOW IGNORING:"));
break; break;
} }
inboundRing->mark(); inboundRing->mark(runningClientId);
inboundRing->print(runningClientId); // prefix inbound with client id
loopState=IPD_DATA; loopState=IPD_DATA;
break; break;
} }
@ -181,10 +174,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
break; break;
case IPD_DATA: // reading data case IPD_DATA: // reading data
inboundRing->write(ch); inboundRing->write(ch);
dataLength--; dataLength--;
if (dataLength == 0) { if (dataLength == 0) {
inboundRing->commit(); inboundRing->commit();
loopState = ANYTHING; loopState = ANYTHING;
} }
break; break;