mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 08:06:13 +01:00
Buffer overflow resilience
And diag output of replies
This commit is contained in:
parent
a16b3a1fa6
commit
6833d82789
|
@ -28,11 +28,12 @@ RingStream::RingStream( const uint16_t len)
|
||||||
_pos_read=0;
|
_pos_read=0;
|
||||||
_buffer[0]=0;
|
_buffer[0]=0;
|
||||||
_overflow=false;
|
_overflow=false;
|
||||||
|
_mark=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RingStream::write(uint8_t byte) {
|
size_t RingStream::write(uint8_t b) {
|
||||||
if (_overflow) return 0;
|
if (_overflow) return 0;
|
||||||
_buffer[_pos_write] = byte;
|
_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) {
|
||||||
|
@ -63,3 +64,23 @@ int RingStream::count() {
|
||||||
}
|
}
|
||||||
return counter;
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -30,12 +30,16 @@ class RingStream : public Print {
|
||||||
using Print::write;
|
using Print::write;
|
||||||
int read();
|
int read();
|
||||||
int count();
|
int count();
|
||||||
|
int freeSpace();
|
||||||
|
void mark();
|
||||||
|
bool commit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _len;
|
int _len;
|
||||||
int _pos_write;
|
int _pos_write;
|
||||||
int _pos_read;
|
int _pos_read;
|
||||||
bool _overflow;
|
bool _overflow;
|
||||||
|
int _mark;
|
||||||
byte * _buffer;
|
byte * _buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,12 @@ void WifiInboundHandler::loop1() {
|
||||||
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->print(clientId);
|
outboundRing->print(clientId);
|
||||||
CommandDistributor::parse(clientId,cmd,outboundRing);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,8 +98,11 @@ 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++) wifiStream->write(outboundRing->read());
|
int cout=outboundRing->read();
|
||||||
|
wifiStream->write(cout);
|
||||||
|
if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise
|
||||||
|
}
|
||||||
outboundRing->read(); // drop the end marker
|
outboundRing->read(); // drop the end marker
|
||||||
clientPendingCIPSEND=-1;
|
clientPendingCIPSEND=-1;
|
||||||
pendingCipsend=false;
|
pendingCipsend=false;
|
||||||
|
@ -159,6 +165,12 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (Diag::WIFI) DIAG(F("\nWifi inbound data(%d:%d):"),runningClientId,dataLength);
|
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
|
inboundRing->print(runningClientId); // prefix inbound with client id
|
||||||
loopState=IPD_DATA;
|
loopState=IPD_DATA;
|
||||||
break;
|
break;
|
||||||
|
@ -170,11 +182,16 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
||||||
inboundRing->write(ch);
|
inboundRing->write(ch);
|
||||||
dataLength--;
|
dataLength--;
|
||||||
if (dataLength == 0) {
|
if (dataLength == 0) {
|
||||||
inboundRing->write((byte)0);
|
inboundRing->commit();
|
||||||
loopState = ANYTHING;
|
loopState = ANYTHING;
|
||||||
}
|
}
|
||||||
break;
|
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
|
case GOT_CLIENT_ID: // got x before CLOSE or CONNECTED
|
||||||
loopState=(ch==',') ? GOT_CLIENT_ID2: SKIPTOEND;
|
loopState=(ch==',') ? GOT_CLIENT_ID2: SKIPTOEND;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -32,6 +32,7 @@ class WifiInboundHandler {
|
||||||
IPD5, // got +IPD,c
|
IPD5, // got +IPD,c
|
||||||
IPD6_LENGTH, // got +IPD,c, reading length
|
IPD6_LENGTH, // got +IPD,c, reading length
|
||||||
IPD_DATA, // got +IPD,c,ll,: collecting data
|
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_ID, // clientid prefix to CONNECTED / CLOSED
|
||||||
GOT_CLIENT_ID2, // clientid prefix to CONNECTED / CLOSED
|
GOT_CLIENT_ID2, // clientid prefix to CONNECTED / CLOSED
|
||||||
|
@ -44,8 +45,8 @@ class WifiInboundHandler {
|
||||||
INBOUND_STATE loop2();
|
INBOUND_STATE loop2();
|
||||||
Stream * wifiStream;
|
Stream * wifiStream;
|
||||||
|
|
||||||
static const int INBOUND_RING = 200;
|
static const int INBOUND_RING = 512;
|
||||||
static const int OUTBOUND_RING = 1024;
|
static const int OUTBOUND_RING = 2048;
|
||||||
|
|
||||||
RingStream * inboundRing;
|
RingStream * inboundRing;
|
||||||
RingStream * outboundRing;
|
RingStream * outboundRing;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user