Skip to content

Commit 6440228

Browse files
kjbraceyVeijo Pesonen
authored andcommitted
Fixes ATCmdParser OOB handling performance-wise
The issue is that the process_oob check would only return immediately if no data at all on entry, or when receiving a known OOB. Any other line noise or unknown OOBs could lead to a timeout delay - read the noise or unknown OOB then timeout waiting for another line of input. This revised version modifies the parser to recheck readable after each line end when only looking for OOBs, so it can immediate exit.
1 parent fba0669 commit 6440228

File tree

2 files changed

+15
-50
lines changed

2 files changed

+15
-50
lines changed

platform/ATCmdParser.cpp

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
215215
restart:
216216
_aborted = false;
217217
// Iterate through each line in the expected response
218-
while (response[0]) {
218+
// response being NULL means we just want to check for OOBs
219+
while (!response || response[0]) {
219220
// Since response is const, we need to copy it into our buffer to
220221
// add the line's null terminator and clobber value-matches with asterisks.
221222
//
@@ -224,7 +225,7 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
224225
int offset = 0;
225226
bool whole_line_wanted = false;
226227

227-
while (response[i]) {
228+
while (response && response[i]) {
228229
if (response[i] == '%' && response[i + 1] != '%' && response[i + 1] != '*') {
229230
_buffer[offset++] = '%';
230231
_buffer[offset++] = '*';
@@ -257,6 +258,11 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
257258
int j = 0;
258259

259260
while (true) {
261+
// If just peeking for OOBs, and at start of line, check
262+
// readability
263+
if (!response && j == 0 && !_fh->readable()) {
264+
return false;
265+
}
260266
// Receive next character
261267
int c = getc();
262268
if (c < 0) {
@@ -284,6 +290,7 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
284290
if ((unsigned)j == oob->len && memcmp(
285291
oob->prefix, _buffer + offset, oob->len) == 0) {
286292
debug_if(_dbg_on, "AT! %s\n", oob->prefix);
293+
_oob_cb_count++;
287294
oob->cb();
288295

289296
if (_aborted) {
@@ -302,7 +309,7 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
302309
// Don't attempt scanning until we get delimiter if they included it in format
303310
// This allows recv("Foo: %s\n") to work, and not match with just the first character of a string
304311
// (scanf does not itself match whitespace in its format string, so \n is not significant to it)
305-
} else {
312+
} else if (response) {
306313
sscanf(_buffer + offset, _buffer, &count);
307314
}
308315

@@ -388,52 +395,9 @@ void ATCmdParser::abort()
388395

389396
bool ATCmdParser::process_oob()
390397
{
391-
if (!_fh->readable()) {
392-
return false;
393-
}
394-
395-
int i = 0;
396-
while (true) {
397-
// Receive next character
398-
int c = getc();
399-
if (c < 0) {
400-
return false;
401-
}
402-
// Simplify newlines (borrowed from retarget.cpp)
403-
if ((c == CR && _in_prev != LF) ||
404-
(c == LF && _in_prev != CR)) {
405-
_in_prev = c;
406-
c = '\n';
407-
} else if ((c == CR && _in_prev == LF) ||
408-
(c == LF && _in_prev == CR)) {
409-
_in_prev = c;
410-
// onto next character
411-
continue;
412-
} else {
413-
_in_prev = c;
414-
}
415-
_buffer[i++] = c;
416-
_buffer[i] = 0;
417-
418-
// Check for oob data
419-
struct oob *oob = _oobs;
420-
while (oob) {
421-
if (i == (int)oob->len && memcmp(
422-
oob->prefix, _buffer, oob->len) == 0) {
423-
debug_if(_dbg_on, "AT! %s\r\n", oob->prefix);
424-
oob->cb();
425-
return true;
426-
}
427-
oob = oob->next;
428-
}
429-
430-
// Clear the buffer when we hit a newline or ran out of space
431-
// running out of space usually means we ran into binary data
432-
if (((i + 1) >= _buffer_size) || (c == '\n')) {
433-
debug_if(_dbg_on, "AT< %s", _buffer);
434-
i = 0;
435-
}
436-
}
398+
int pre_count = _oob_cb_count;
399+
recv(NULL);
400+
return _oob_cb_count != pre_count;
437401
}
438402

439403
}

platform/ATCmdParser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class ATCmdParser : private NonCopyable<ATCmdParser> {
6666
// Parsing information
6767
const char *_output_delimiter;
6868
int _output_delim_size;
69+
int _oob_cb_count;
6970
char _in_prev;
7071
bool _dbg_on;
7172
bool _aborted;
@@ -91,7 +92,7 @@ class ATCmdParser : private NonCopyable<ATCmdParser> {
9192
*/
9293
ATCmdParser(FileHandle *fh, const char *output_delimiter = "\r",
9394
int buffer_size = 256, int timeout = 8000, bool debug = false)
94-
: _fh(fh), _buffer_size(buffer_size), _in_prev(0), _oobs(NULL)
95+
: _fh(fh), _buffer_size(buffer_size), _oob_cb_count(0), _in_prev(0), _oobs(NULL)
9596
{
9697
_buffer = new char[buffer_size];
9798
set_timeout(timeout);

0 commit comments

Comments
 (0)