1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-30 03:26:13 +01:00

protect ringstream

This commit is contained in:
Harald Barth 2021-11-06 23:51:32 +01:00
parent d7e46ac625
commit 55c7a0a1e8
2 changed files with 18 additions and 1 deletions

View File

@ -30,28 +30,36 @@ RingStream::RingStream( const uint16_t len)
_overflow=false; _overflow=false;
_mark=0; _mark=0;
_count=0; _count=0;
#if defined(ARDUINO_ARCH_ESP32)
portMUX_TYPE _bufMux = portMUX_INITIALIZER_UNLOCKED;
#endif
} }
size_t RingStream::write(uint8_t b) { size_t RingStream::write(uint8_t b) {
if (_overflow) return 0; if (_overflow) return 0;
portENTER_CRITICAL(&_bufMux);
_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;
portEXIT_CRITICAL(&_bufMux);
return 0; return 0;
} }
_count++; _count++;
portEXIT_CRITICAL(&_bufMux);
return 1; return 1;
} }
int RingStream::read(byte advance) { int RingStream::read(byte advance) {
if ((_pos_read==_pos_write) && !_overflow) return -1; // empty if ((_pos_read==_pos_write) && !_overflow) return -1; // empty
if (_pos_read == _mark) return -1; if (_pos_read == _mark) return -1;
portENTER_CRITICAL(&_bufMux);
byte b=_buffer[_pos_read]; byte b=_buffer[_pos_read];
_pos_read += advance; _pos_read += advance;
if (_pos_read==_len) _pos_read=0; if (_pos_read==_len) _pos_read=0;
_overflow=false; _overflow=false;
portEXIT_CRITICAL(&_bufMux);
return b; return b;
} }
@ -70,11 +78,13 @@ int RingStream::freeSpace() {
// mark start of message with client id (0...9) // mark start of message with client id (0...9)
void RingStream::mark(uint8_t b) { void RingStream::mark(uint8_t b) {
//DIAG(F("Mark1 len=%d count=%d pr=%d pw=%d m=%d"),_len, _count,_pos_read,_pos_write,_mark); //DIAG(F("Mark1 len=%d count=%d pr=%d pw=%d m=%d"),_len, _count,_pos_read,_pos_write,_mark);
portENTER_CRITICAL(&_bufMux);
_mark=_pos_write; _mark=_pos_write;
write(b); // client id write(b); // client id
write((uint8_t)0); // count MSB placemarker write((uint8_t)0); // count MSB placemarker
write((uint8_t)0); // count LSB placemarker write((uint8_t)0); // count LSB placemarker
_count=0; _count=0;
portEXIT_CRITICAL(&_bufMux);
} }
// peekTargetMark is used by the parser stash routines to know which client // peekTargetMark is used by the parser stash routines to know which client
@ -89,16 +99,19 @@ void RingStream::info() {
bool RingStream::commit() { bool RingStream::commit() {
//DIAG(F("Commit1 len=%d count=%d pr=%d pw=%d m=%d"),_len, _count,_pos_read,_pos_write,_mark); //DIAG(F("Commit1 len=%d count=%d pr=%d pw=%d m=%d"),_len, _count,_pos_read,_pos_write,_mark);
portENTER_CRITICAL(&_bufMux);
if (_overflow) { if (_overflow) {
DIAG(F("RingStream(%d) commit(%d) OVERFLOW"),_len, _count); DIAG(F("RingStream(%d) commit(%d) OVERFLOW"),_len, _count);
// just throw it away // just throw it away
_pos_write=_mark; _pos_write=_mark;
_overflow=false; _overflow=false;
portEXIT_CRITICAL(&_bufMux);
return false; // commit failed return false; // commit failed
} }
if (_count==0) { if (_count==0) {
// ignore empty response // ignore empty response
_pos_write=_mark; _pos_write=_mark;
portEXIT_CRITICAL(&_bufMux);
return true; // true=commit ok return true; // true=commit ok
} }
// Go back to the _mark and inject the count 1 byte later // Go back to the _mark and inject the count 1 byte later
@ -110,5 +123,6 @@ bool RingStream::commit() {
_buffer[_mark]=lowByte(_count); _buffer[_mark]=lowByte(_count);
_mark=_len+1; _mark=_len+1;
//DIAG(F("Commit2 len=%d count=%d pr=%d pw=%d m=%d"),_len, _count,_pos_read,_pos_write,_mark); //DIAG(F("Commit2 len=%d count=%d pr=%d pw=%d m=%d"),_len, _count,_pos_read,_pos_write,_mark);
portEXIT_CRITICAL(&_bufMux);
return true; // commit worked return true; // commit worked
} }

View File

@ -46,6 +46,9 @@ class RingStream : public Print {
int _mark; int _mark;
int _count; int _count;
byte * _buffer; byte * _buffer;
#if defined(ARDUINO_ARCH_ESP32)
portMUX_TYPE _bufMux;
#endif
}; };
#endif #endif