Skip to content

Commit 2be16f8

Browse files
committed
Added buffer checks to command interfaces
Limits risk over overflowing thread ram during command flooding
1 parent 7f8e79c commit 2be16f8

14 files changed

Lines changed: 75 additions & 18 deletions

Firmware/FFBoard/Inc/CDCcomm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class CDCcomm {
1717

1818
static uint16_t cdcSend(std::string* reply,uint8_t itf);
1919
static void cdcFinished(uint8_t itf = 0);
20+
static uint32_t remainingData(uint8_t itf = 0);
2021

2122
private:
2223
static bool usb_busy_retry;

Firmware/FFBoard/Inc/CmdParser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ class CmdParser {
2828
void clear();
2929
bool add(char* Buf, uint32_t *Len);
3030
bool parse(std::vector<ParsedCommand>& commands);
31-
uint32_t bufferCapacity();
31+
int32_t bufferCapacity();
3232

3333
void setClearBufferTimeout(uint32_t timeout);
3434

3535
private:
3636
std::string buffer;
37-
uint32_t reservedBuffer = 0;
37+
int32_t reservedBuffer = 100;
38+
int32_t bufferMaxCapacity = 512;
3839

3940
uint32_t clearBufferTimeout = 0;
4041
uint32_t lastAddTime = 0;

Firmware/FFBoard/Inc/CommandInterface.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class CommandInterface {
3232
virtual bool hasNewCommands();
3333
static void broadcastCommandReplyAsync(std::vector<CommandReply>& reply,CommandHandler* handler, uint32_t cmdId,CMDtype type);
3434
virtual void sendReplies(std::vector<CommandResult>& results,CommandInterface* originalInterface); // All commands from batch done
35+
virtual bool readyToSend();
3536
protected:
3637
bool parserReady = false;
3738
};
@@ -43,6 +44,7 @@ class StringCommandInterface : public CommandInterface{
4344
public:
4445
StringCommandInterface(uint32_t reservedBuffer = 16) : parser(CmdParser(reservedBuffer)){}
4546
bool addBuf(char* Buf, uint32_t *Len);
47+
uint32_t bufferCapacity();
4648
bool getNewCommands(std::vector<ParsedCommand>& commands) override;
4749
static void formatReply(std::string& reply,const std::vector<CommandResult>& results,const bool formatWriteAsRead=false);
4850
static std::string formatOriginalCommandFromResult(const ParsedCommand& originalCommand,CommandHandler* commandHandler,const bool formatWriteAsRead=false);
@@ -64,7 +66,7 @@ class CDC_CommandInterface : public StringCommandInterface{
6466

6567
void sendReplies(std::vector<CommandResult>& results,CommandInterface* originalInterface) override;
6668
const std::string getHelpstring(){return "CDC interface. " + StringCommandInterface::getHelpstring();};
67-
69+
bool readyToSend() override;
6870
private:
6971
bool enableBroadcastFromOtherInterfaces = true;
7072
const uint32_t parserTimeout = 2000;

Firmware/FFBoard/Inc/HidCommandInterface.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,16 @@ class HID_CommandInterface : public CommandInterface, public cpp_freertos::Threa
4747
bool sendHidCmd(HID_CMD_Data_t* data);
4848
void queueReplyValues(CommandReply& reply,ParsedCommand& command);
4949
void transferComplete(uint8_t itf, uint8_t const* report, uint8_t len);
50-
50+
bool readyToSend();
5151
void Run();
5252

5353
private:
5454
std::vector<ParsedCommand> commands;
5555
std::vector<HID_CMD_Data_t> outBuffer;
5656
bool enableBroadcastFromOtherInterfaces = true; // TODO make configurable via command
5757
static cpp_freertos::BinarySemaphore threadSem;
58-
58+
const uint32_t maxQueuedReplies = 50;
59+
const uint32_t maxQueuedRepliesBroadcast = 10; // Must be smaller than maxQueuedReplies
5960

6061
};
6162

Firmware/FFBoard/Inc/constants.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212

13-
static const uint8_t SW_VERSION_INT[3] = {1,6,1}; // Version as array. 8 bit each!
13+
static const uint8_t SW_VERSION_INT[3] = {1,6,2}; // Version as array. 8 bit each!
1414

1515
#define MAX_AXIS 2 // ONLY USE 2 for now else screws HID Reports
1616

Firmware/FFBoard/Src/CDCcomm.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ void CDCcomm::cdcFinished(uint8_t itf){
3838
}
3939
}
4040

41+
uint32_t CDCcomm::remainingData(uint8_t itf){
42+
return CDCcomm::remainingStrs[itf].size();
43+
}
44+
4145
/**
4246
* Sends a string via CDC
4347
* If not everything can be sent it will be buffered for later in a new string

Firmware/FFBoard/Src/CmdParser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ void CmdParser::setClearBufferTimeout(uint32_t timeout){
5050
this->clearBufferTimeout = timeout;
5151
}
5252

53-
uint32_t CmdParser::bufferCapacity(){
54-
return buffer.capacity() - buffer.size();
53+
int32_t CmdParser::bufferCapacity(){
54+
return std::max<int32_t>(bufferMaxCapacity - buffer.size(),0);
5555
}
5656

5757

Firmware/FFBoard/Src/CommandInterface.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ bool CommandInterface::hasNewCommands(){
6363
return parserReady;
6464
}
6565

66+
/**
67+
* Returns true if it can send replies.
68+
* False if the command thread should wait until previous replies are processed
69+
*/
70+
bool CommandInterface::readyToSend(){
71+
return true;
72+
}
73+
6674

6775
/*
6876
*
@@ -88,6 +96,10 @@ bool StringCommandInterface::addBuf(char* Buf, uint32_t *Len){
8896
return res;
8997
}
9098

99+
uint32_t StringCommandInterface::bufferCapacity(){
100+
return parser.bufferCapacity();
101+
}
102+
91103
void StringCommandInterface::formatReply(std::string& reply,const std::vector<CommandResult>& results,const bool formatWriteAsRead){
92104
//uint16_t lastId = 0xFFFF;
93105
for(const CommandResult& result : results){ // All commands processed this batch
@@ -214,16 +226,24 @@ CDC_CommandInterface::~CDC_CommandInterface() {
214226

215227

216228
void CDC_CommandInterface::sendReplies(std::vector<CommandResult>& results,CommandInterface* originalInterface){
217-
if( (!enableBroadcastFromOtherInterfaces && originalInterface != this) || !tud_ready() ){
229+
if( (!enableBroadcastFromOtherInterfaces && originalInterface != this) ){
218230
return;
219231
}
232+
220233
std::string replystr;
221234
replystr.reserve(100);
222235
StringCommandInterface::formatReply(replystr,results, originalInterface != this && originalInterface != nullptr);
223236
if(!replystr.empty())
224237
CDCcomm::cdcSend(&replystr, 0);
225238
}
226239

240+
/**
241+
* Ready to send if there is no data in the backup buffer of the cdc port
242+
*/
243+
bool CDC_CommandInterface::readyToSend(){
244+
return CDCcomm::remainingData(0) == 0;
245+
}
246+
227247

228248

229249
/*************************
@@ -233,7 +253,6 @@ void CDC_CommandInterface::sendReplies(std::vector<CommandResult>& results,Comma
233253
*
234254
*/
235255

236-
237256
extern UARTPort external_uart; // defined in cpp_target_config.cpp
238257
UART_CommandInterface::UART_CommandInterface(uint32_t baud) : StringCommandInterface(128), UARTDevice(external_uart),Thread("UARTCMD", 256, 36), baud(baud){ //
239258
uartconfig = uartport->getConfig();
@@ -280,7 +299,7 @@ void UART_CommandInterface::Run(){
280299
//}
281300

282301
void UART_CommandInterface::sendReplies(std::vector<CommandResult>& results,CommandInterface* originalInterface){
283-
if( (!enableBroadcastFromOtherInterfaces && originalInterface != this) || !tud_ready() ){
302+
if( (!enableBroadcastFromOtherInterfaces && originalInterface != this) ){
284303
return;
285304
}
286305

@@ -297,7 +316,7 @@ void UART_CommandInterface::sendReplies(std::vector<CommandResult>& results,Comm
297316
void UART_CommandInterface::uartRcv(char& buf){
298317
uint32_t len = 1;
299318
BaseType_t savedInterruptStatus = cpp_freertos::CriticalSection::EnterFromISR();
300-
if(this->parser.bufferCapacity() > len) // Check buffer because we can't allocate more memory inside the ISR safely at the moment
319+
if(this->parser.bufferCapacity() > (int32_t)len) // Check buffer because we can't allocate more memory inside the ISR safely at the moment
301320
StringCommandInterface::addBuf(&buf, &len);
302321
cpp_freertos::CriticalSection::ExitFromISR(savedInterruptStatus);
303322
}

Firmware/FFBoard/Src/HidCommandInterface.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ void HID_CommandInterface::Run(){
5252
}
5353
}
5454

55+
bool HID_CommandInterface::readyToSend(){
56+
return this->outBuffer.size() < maxQueuedReplies;
57+
}
5558

5659
void HID_CommandInterface::sendReplies(std::vector<CommandResult>& results,CommandInterface* originalInterface){
5760

@@ -61,6 +64,10 @@ void HID_CommandInterface::sendReplies(std::vector<CommandResult>& results,Comma
6164
continue;
6265

6366
if( (originalInterface != this && enableBroadcastFromOtherInterfaces) || ( result.type == CommandStatus::OK && replies.empty() ) ){ // Request was sent by a different interface
67+
if(this->outBuffer.size() > maxQueuedRepliesBroadcast){
68+
continue; // for now we just throw away broadcasts if the buffer contains too many pending replies.
69+
}
70+
6471
CommandReply reply; // Fake reply
6572

6673
// return original command as get value if it was a set command

Firmware/FFBoard/Src/global_callbacks.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,13 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf){
237237

238238
void tud_cdc_rx_cb(uint8_t itf){
239239
pulseSysLed();
240-
uint8_t buf[64];
241-
uint32_t count = tud_cdc_n_read(itf,buf, sizeof(buf));
242-
if(mainclass!=nullptr)
243-
mainclass->cdcRcv((char*)buf,&count);
240+
// uint8_t buf[64];
241+
if(mainclass!=nullptr){
242+
mainclass->cdcRcvReady(itf);
243+
}
244+
// uint32_t count = tud_cdc_n_read(itf,buf, std::min<uint32_t>(mainclass->cdcFree(),sizeof(buf)));
245+
// mainclass->cdcRcv((char*)buf,&count);
246+
// }
244247
}
245248

246249
void tud_cdc_tx_complete_cb(uint8_t itf){

0 commit comments

Comments
 (0)