From 11ee33c12733a442642c9099debe3d9e56b2e091 Mon Sep 17 00:00:00 2001 From: David Alonso de la Torre Date: Sat, 23 Dec 2023 10:05:28 +0100 Subject: [PATCH] SMS: Increase timeout for send and get. Fix text SMS parsing when CRLF is contained in the text. --- .../cellular/framework/API/ATHandler.h | 13 +++++++ .../source/framework/AT/AT_CellularSMS.cpp | 28 +++++++++++-- .../source/framework/device/ATHandler.cpp | 39 +++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/connectivity/cellular/include/cellular/framework/API/ATHandler.h b/connectivity/cellular/include/cellular/framework/API/ATHandler.h index da2a6ea124a..e2505a5aac5 100644 --- a/connectivity/cellular/include/cellular/framework/API/ATHandler.h +++ b/connectivity/cellular/include/cellular/framework/API/ATHandler.h @@ -318,6 +318,13 @@ class ATHandler { */ void skip_param(ssize_t len, uint32_t count); + /** Consumes the given length from the reading buffer even if the stop tag has been found + * + * @param len length to be consumed from reading buffer + * @param count number of parameters to be skipped + */ + void skip_param_bytes(ssize_t len, uint32_t count); + /** Reads given number of bytes from receiving buffer without checking any subparameter delimiters, such as comma. * * @param buf output buffer for the read @@ -408,6 +415,12 @@ class ATHandler { */ bool consume_to_stop_tag(); + /** Consumes the received content until current stop tag is found even if stop tag has been found previously + * + * @return true if stop tag is found, false otherwise + */ + bool consume_to_stop_tag_even_stop_tag_found(); + /** Return the last 3GPP error code. * @return last 3GPP error code */ diff --git a/connectivity/cellular/source/framework/AT/AT_CellularSMS.cpp b/connectivity/cellular/source/framework/AT/AT_CellularSMS.cpp index 79ebc908733..13e460188c0 100644 --- a/connectivity/cellular/source/framework/AT/AT_CellularSMS.cpp +++ b/connectivity/cellular/source/framework/AT/AT_CellularSMS.cpp @@ -419,6 +419,7 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c return NSAPI_ERROR_PARAMETER; } + _at.set_at_timeout(10s); _at.lock(); int write_size = 0; @@ -438,6 +439,7 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c _at.cmd_start(ESC); _at.cmd_stop(); _at.unlock(); + _at.restore_at_timeout(); return write_size; } // (IRA 26) must be used to indicate the ending of the message body. @@ -483,6 +485,7 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c sms_count, i + 1, header_len); if (!pdu_str) { _at.unlock(); + _at.restore_at_timeout(); return NSAPI_ERROR_NO_MEMORY; } pdu_len = strlen(pdu_str); @@ -510,6 +513,7 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c _at.cmd_start(ESC); _at.cmd_stop(); _at.unlock(); + _at.restore_at_timeout(); delete [] pdu_str; return msg_write_len; } @@ -523,7 +527,10 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c delete [] pdu_str; remaining_len -= concatenated_sms_length; if (_at.get_last_error() != NSAPI_ERROR_OK) { - return _at.unlock_return_error(); + nsapi_error_t ret = _at.get_last_error(); + _at.unlock(); + _at.restore_at_timeout(); + return ret; } } } @@ -531,6 +538,8 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c _sms_message_ref_number++; nsapi_error_t ret = _at.get_last_error(); _at.unlock(); + _at.restore_at_timeout(); + _at.clear_error(); return (ret == NSAPI_ERROR_OK) ? msg_len : ret; } @@ -696,6 +705,7 @@ nsapi_size_or_error_t AT_CellularSMS::get_sms(char *buf, uint16_t len, char *pho return NSAPI_ERROR_PARAMETER; } + _at.set_at_timeout(10s); _at.lock(); nsapi_size_or_error_t err = list_messages(); @@ -735,6 +745,7 @@ nsapi_size_or_error_t AT_CellularSMS::get_sms(char *buf, uint16_t len, char *pho free_linked_list(); _at.unlock(); + _at.restore_at_timeout(); // update error only when there really was an error, otherwise we return the length if (_at.get_last_error()) { @@ -1027,6 +1038,7 @@ nsapi_error_t AT_CellularSMS::list_messages() int index = 0; int length = 0; char *pdu = NULL; + char buffer[32]; // 32 > SMS_STATUS_SIZE, SMS_MAX_PHONE_NUMBER_SIZE, SMS_MAX_TIME_STAMP_SIZE _at.resp_start("+CMGL:"); while (_at.info_resp()) { @@ -1049,8 +1061,18 @@ nsapi_error_t AT_CellularSMS::list_messages() // +CMGL: ,,,[],[][,,][ // +CMGL: ,,,[],[][,,][...]] index = _at.read_int(); - (void)_at.consume_to_stop_tag(); // consume until - (void)_at.consume_to_stop_tag(); // consume until + _at.read_string(buffer, SMS_STATUS_SIZE); + _at.read_string(buffer, SMS_MAX_PHONE_NUMBER_SIZE); + _at.skip_param(); // + _at.read_string(buffer, SMS_MAX_TIME_STAMP_SIZE); + _at.read_int(); + int size = _at.read_int(); // length + _at.consume_to_stop_tag(); // consume until end of header + if (size > 0) { + // we can not use skip param because we already consumed stop tag + _at.skip_param_bytes(size, 1); + } + _at.consume_to_stop_tag_even_stop_tag_found(); // consume until -> data } if (index >= 0) { diff --git a/connectivity/cellular/source/framework/device/ATHandler.cpp b/connectivity/cellular/source/framework/device/ATHandler.cpp index 034d586a142..68a10384095 100644 --- a/connectivity/cellular/source/framework/device/ATHandler.cpp +++ b/connectivity/cellular/source/framework/device/ATHandler.cpp @@ -484,6 +484,26 @@ void ATHandler::skip_param(ssize_t len, uint32_t count) return; } +void ATHandler::skip_param_bytes(ssize_t len, uint32_t count) +{ + if (!ok_to_proceed()) { + return; + } + + for (uint32_t i = 0; i < count; i++) { + ssize_t read_len = 0; + while (read_len < len) { + int c = get_char(); + if (c == -1) { + set_error(NSAPI_ERROR_DEVICE_ERROR); + return; + } + read_len++; + } + } + return; +} + ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len) { if (!ok_to_proceed()) { @@ -1093,6 +1113,25 @@ bool ATHandler::consume_to_stop_tag() return false; } +bool ATHandler::consume_to_stop_tag_even_stop_tag_found() +{ + if (_error_found) { + return true; + } + + if (!_is_fh_usable) { + _last_err = NSAPI_ERROR_BUSY; + return true; + } + + if (consume_to_tag((const char *)_stop_tag->tag, true)) { + return true; + } + + clear_error(); + return false; +} + // consume by size needed? void ATHandler::resp_stop()