summaryrefslogtreecommitdiff
path: root/fw/esp32/components/eos/cell_sms.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/esp32/components/eos/cell_sms.c')
-rw-r--r--fw/esp32/components/eos/cell_sms.c340
1 files changed, 203 insertions, 137 deletions
diff --git a/fw/esp32/components/eos/cell_sms.c b/fw/esp32/components/eos/cell_sms.c
index ac710f9..f1f8b33 100644
--- a/fw/esp32/components/eos/cell_sms.c
+++ b/fw/esp32/components/eos/cell_sms.c
@@ -15,170 +15,213 @@
static const char *TAG = "EOS SMS";
-static char cmd[256];
+static char _pdu_in[2048];
+static char _pdu_out[2048];
-static char pdu[4096];
-static int pdu_len;
+extern char *at_cmd_buf;
-static uint8_t udh[GSM_UDH_SIZE];
-static int udh_len;
+static ssize_t sms_encode(unsigned char *buffer, uint16_t buf_len, char *pdu, size_t pdu_size) {
+ ucp_t ch;
+ size_t pdu_len;
+ ssize_t rv;
+ int i;
-static uint8_t msg[GSM_MSG_SIZE];
-static int msg_len;
-static uint8_t msg_enc;
+ char *addr;
+ uint8_t addr_type;
+ size_t addr_len;
+
+ uint8_t txt[GSM_UD_SIZE];
+ size_t txt_len;
+
+ uint16_t flags;
+
+ if (buf_len < 2) return EOS_ERR_SIZE;
+ flags = buffer[0] << 8;
+ flags |= buffer[1];
+ buffer += 2;
+ buf_len -= 2;
+
+ if (buf_len < 2) return EOS_ERR_SIZE;
+ switch (buffer[0]) {
+ case EOS_CELL_SMS_ADDRTYPE_INTL:
+ addr_type = GSM_EXT | GSM_TON_INTERNATIONAL | GSM_NPI_TELEPHONE;
+ break;
+
+ case EOS_CELL_SMS_ADDRTYPE_OTHER:
+ addr_type = GSM_EXT | GSM_TON_UNKNOWN | GSM_NPI_TELEPHONE;
+ break;
+
+ default:
+ return EOS_ERR;
+ }
+ addr_len = buffer[1];
+ addr = (char *)buffer + 2;
-static char orig_addr[GSM_ADDR_SIZE];
-static int orig_addr_len;
-static uint8_t orig_addr_type;
+ if (buf_len < 2 + addr_len) return EOS_ERR_SIZE;
+ buffer += 2 + addr_len;
+ buf_len -= 2 + addr_len;
-static char smsc_addr[GSM_ADDR_SIZE];
-static int smsc_addr_len;
-static uint8_t smsc_addr_type;
+ i = 0;
+ txt_len = 0;
+ while (i < buf_len) {
+ int _rv;
+
+ if (buf_len - i < 4) {
+ _rv = utf8_len_str(buffer + i);
+ if (_rv < 0) return EOS_ERR;
+ if (buf_len - i < _rv) return EOS_ERR_SIZE;
+ }
-static char smsc_timestamp[GSM_TS_SIZE];
+ _rv = utf8_dec(buffer + i, &ch);
+ if (_rv < 0) return EOS_ERR;
+ if (ch >= 0xffff) return EOS_ERR;
+ i += _rv;
-uint16_t flags;
+ _rv = gsm_ucs2_to_7bit((char *)txt + txt_len, sizeof(txt) - txt_len, ch);
+ if (_rv < 0) return EOS_ERR;
+ txt_len += _rv;
+ }
+
+ if (pdu_size < 2) return EOS_ERR_SIZE;
+ pdu_putc(pdu, 0);
-static int sms_decode(unsigned char *buf, uint16_t *_len) {
- int i, j, rv;
- uint16_t len = 0;
- uint8_t smsc_info, smsc_info_len;
+ rv = gsm_sms_enc(pdu + 2, pdu_size - 2, addr, addr_len, addr_type, NULL, 0, txt, txt_len, GSM_ENC_7BIT, flags);
+ if (rv < 0) return EOS_ERR;
+ pdu_len = rv + 2;
+
+ return pdu_len;
+}
- if (pdu_len < 2) return EOS_ERR;
- smsc_info = pdu_getc(pdu);
+static ssize_t sms_decode(char *pdu, size_t pdu_len, unsigned char *buf, uint16_t buf_size) {
+ uint16_t buf_len = 0;
+ ssize_t rv;
+ int i, j;
+
+ char smsc_addr[GSM_ADDR_SIZE];
+ size_t smsc_addr_len;
+ uint8_t smsc_info, smsc_info_len, smsc_addr_type;
+
+ char orig_addr[GSM_ADDR_SIZE];
+ size_t orig_addr_len;
+ uint8_t orig_addr_type;
+
+ uint8_t udh[GSM_UDH_SIZE];
+ size_t udh_len;
+
+ uint8_t txt[GSM_UD_SIZE];
+ size_t txt_len;
+ uint8_t txt_enc;
+
+ char smsc_timestamp[GSM_TS_SIZE];
+ uint16_t flags;
+
+ if (pdu_len < 2) return EOS_ERR_SIZE;
+ rv = pdu_getc(pdu, &smsc_info);
+ if (rv < 0) return rv;
smsc_info_len = 2 * (smsc_info + 1);
- if (pdu_len < smsc_info_len) return EOS_ERR;
+ if (pdu_len < smsc_info_len) return EOS_ERR_SIZE;
if (smsc_info > 1) {
- pdu_putc((smsc_info - 1) * 2, pdu);
+ /* SMSC address - currently not used */
+ pdu_putc(pdu, (smsc_info - 1) * 2);
rv = gsm_addr_dec(pdu, pdu_len, smsc_addr, &smsc_addr_len, &smsc_addr_type);
if (rv < 0) smsc_addr_len = 0;
}
- rv = gsm_sms_dec(pdu + smsc_info_len, pdu_len - smsc_info_len, orig_addr, &orig_addr_len, &orig_addr_type, udh, &udh_len, msg, &msg_len, smsc_timestamp, &msg_enc, &flags);
- if (rv == GSM_ERR_NOT_SUPPORTED) ESP_LOGE(TAG, "Message not supported: %s", pdu);
- if (rv < 0) return rv;
- if (msg_enc == GSM_ENC_8BIT) return EOS_ERR;
+ rv = gsm_sms_dec(pdu + smsc_info_len, pdu_len - smsc_info_len, orig_addr, &orig_addr_len, &orig_addr_type, udh, &udh_len, txt, &txt_len, &txt_enc, smsc_timestamp, &flags);
+ if ((rv == GSM_ERR_NOTSUPPORTED) || (txt_enc == GSM_ENC_8BIT)) {
+ ESP_LOGE(TAG, "Message not supported: %s", pdu);
+ return EOS_ERR_NOTSUPPORTED;
+ }
+ if (rv < 0) return EOS_ERR;
+ if (buf_size < buf_len + 2) return EOS_ERR_SIZE;
buf[0] = flags >> 8;
buf[1] = flags;
- len += 2;
+ buf_len += 2;
- memcpy(buf + len, smsc_timestamp, GSM_TS_SIZE);
- len += GSM_TS_SIZE;
+ if (buf_size < buf_len + GSM_TS_SIZE) return EOS_ERR_SIZE;
+ memcpy(buf + buf_len, smsc_timestamp, GSM_TS_SIZE);
+ buf_len += GSM_TS_SIZE;
if ((orig_addr_type & GSM_TON) == GSM_TON_ALPHANUMERIC) {
- buf[len] = EOS_CELL_SMS_ADDRTYPE_ALPHA;
- buf[len + 1] = 0;
- len += 2;
+ if (buf_size < buf_len + 2) return EOS_ERR_SIZE;
+ buf[buf_len] = EOS_CELL_SMS_ADDRTYPE_ALPHA;
+ buf[buf_len + 1] = 0;
+ buf_len += 2;
i = 0;
j = 0;
while (i < orig_addr_len) {
uint16_t ch;
+ int _rv;
- rv = gsm_7bit_to_ucs2((char *)orig_addr + i, orig_addr_len - i, &ch);
- if (rv < 0) return EOS_ERR;
- i += rv;
- rv = utf8_enc(ch, buf + len + j);
- if (rv < 0) return EOS_ERR;
- j += rv;
+ _rv = gsm_7bit_to_ucs2((char *)orig_addr + i, orig_addr_len - i, &ch);
+ if (_rv < 0) return EOS_ERR;
+ i += _rv;
+
+ if (buf_size - buf_len - j < 4) {
+ _rv = utf8_len_ch(ch);
+ if (_rv < 0) return EOS_ERR;
+ if (buf_size - buf_len - j < _rv) return EOS_ERR_SIZE;
+ }
+
+ _rv = utf8_enc(ch, buf + buf_len + j);
+ if (_rv < 0) return EOS_ERR;
+ j += _rv;
}
- buf[len - 1] = j;
- len += j;
+ buf[buf_len - 1] = j;
+ buf_len += j;
} else {
- buf[len] = ((orig_addr_type & GSM_TON) == GSM_TON_INTERNATIONAL) ? EOS_CELL_SMS_ADDRTYPE_INTL : EOS_CELL_SMS_ADDRTYPE_OTHER;
- buf[len + 1] = orig_addr_len;
- len += 2;
- memcpy(buf + len, orig_addr, orig_addr_len);
- len += orig_addr_len;
+ if (buf_size < buf_len + 2) return EOS_ERR_SIZE;
+ buf[buf_len] = ((orig_addr_type & GSM_TON) == GSM_TON_INTERNATIONAL) ? EOS_CELL_SMS_ADDRTYPE_INTL : EOS_CELL_SMS_ADDRTYPE_OTHER;
+ buf[buf_len + 1] = orig_addr_len;
+ buf_len += 2;
+
+ if (buf_size < buf_len + orig_addr_len) return EOS_ERR_SIZE;
+ memcpy(buf + buf_len, orig_addr, orig_addr_len);
+ buf_len += orig_addr_len;
}
i = 0;
j = 0;
- while (i < msg_len) {
- utf32_t ch;
+ while (i < txt_len) {
+ ucp_t ch;
+ int _rv;
- if (msg_enc == GSM_ENC_7BIT) {
+ if (txt_enc == GSM_ENC_7BIT) {
uint16_t _ch;
- rv = gsm_7bit_to_ucs2((char *)msg + i, msg_len - i, &_ch);
+ _rv = gsm_7bit_to_ucs2((char *)txt + i, txt_len - i, &_ch);
+ if (_rv < 0) return EOS_ERR;
ch = _ch;
} else {
- if (((msg_len - i) < 4) && (utf16_len(msg + i) > 2)) {
- rv = EOS_ERR;
- } else {
- rv = utf16_dec(msg + i, &ch);
+ if (txt_len - i < 2) return EOS_ERR_SIZE;
+ if (txt_len - i < 4) {
+ _rv = utf16_len_str(txt + i);
+ if (_rv < 0) return EOS_ERR;
+ if (txt_len - i < _rv) return EOS_ERR_SIZE;
}
+ _rv = utf16_dec(txt + i, &ch);
+ if (_rv < 0) return EOS_ERR;
}
- if (rv < 0) return EOS_ERR;
- i += rv;
+ i += _rv;
- rv = utf8_enc(ch, buf + len + j);
- if (rv < 0) return EOS_ERR;
- j += rv;
- }
- buf[len + j] = '\0';
- len += j + 1;
- *_len = len;
-
- return EOS_OK;
-}
-
-static int sms_encode(unsigned char *buffer, uint16_t len) {
- utf32_t ch;
- int i, rv;
- char *addr;
- uint8_t addr_type;
- int addr_len;
-
- if (len < 2) return EOS_ERR;
- flags = buffer[0] << 8;
- flags |= buffer[1];
- buffer += 2;
- len -= 2;
-
- if (len < 2) return EOS_ERR;
- switch (buffer[0]) {
- case EOS_CELL_SMS_ADDRTYPE_INTL:
- addr_type = GSM_EXT | GSM_TON_INTERNATIONAL | GSM_NPI_TELEPHONE;
- break;
-
- case EOS_CELL_SMS_ADDRTYPE_OTHER:
- addr_type = GSM_EXT | GSM_TON_UNKNOWN | GSM_NPI_TELEPHONE;
- break;
-
- default:
- return EOS_ERR;
- }
- addr_len = buffer[1];
- addr = (char *)buffer + 2;
-
- if (len < 2 + addr_len) return EOS_ERR;
- buffer += 2 + addr_len;
- len -= 2 + addr_len;
-
- i = 0;
- msg_len = 0;
- while (i < len) {
- rv = utf8_dec(buffer + i, &ch);
- if (rv < 0) return EOS_ERR;
- if (ch >= 0xffff) return EOS_ERR;
- i += rv;
+ if (buf_size - buf_len - j < 4) {
+ _rv = utf8_len_ch(ch);
+ if (_rv < 0) return EOS_ERR;
+ if (buf_size - buf_len - j < _rv) return EOS_ERR_SIZE;
+ }
- rv = gsm_ucs2_to_7bit(ch, (char *)msg + msg_len, sizeof(msg) - msg_len);
- if (rv < 0) return EOS_ERR;
- msg_len += rv;
+ _rv = utf8_enc(ch, buf + buf_len + j);
+ if (_rv < 0) return EOS_ERR;
+ j += _rv;
}
+ if (buf_size < buf_len + j + 1) return EOS_ERR_SIZE;
+ buf[buf_len + j] = '\0';
+ buf_len += j + 1;
- pdu_putc(0, pdu);
- rv = gsm_sms_enc(addr, addr_len, addr_type, NULL, 0, msg, msg_len, GSM_ENC_7BIT, flags, pdu + 2, sizeof(pdu) - 4);
- if (rv < 0) return EOS_ERR;
- pdu_len = rv;
- pdu[pdu_len + 2] = CTRL_Z;
- pdu[pdu_len + 3] = '\0';
-
- return EOS_OK;
+ return buf_len;
}
void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) {
@@ -190,34 +233,40 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b
case EOS_CELL_MTYPE_SMS_LIST: {
if (buf_len < 1) return;
- rv = snprintf(cmd, sizeof(cmd), "AT+CMGL=%d\r", buffer[0]);
- if ((rv < 0) || (rv >= sizeof(cmd))) return;
+ rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CMGL=%d\r", buffer[0]);
+ if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return;
rv = eos_modem_take(1000);
if (rv) return;
- at_cmd(cmd);
+ at_cmd(at_cmd_buf);
do {
unsigned char *buf;
- uint16_t len;
+ uint16_t buf_len;
+
+ char *pdu = _pdu_in;
+ size_t pdu_size = sizeof(_pdu_in);
+ size_t pdu_len;
+ ssize_t _rv;
rv = at_expect("^\\+CMGL: [0-9]+,[0-9],.*,[0-9]+$", "^OK", 1000);
if (rv) break;
- rv = eos_modem_readln(pdu, sizeof(pdu), 1000);
+ rv = eos_modem_readln(pdu, pdu_size, 1000);
if (rv) break;
pdu_len = strlen(pdu);
buf = eos_net_alloc();
buf[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_LIST_ITEM;
- rv = sms_decode(buf + 1, &len);
- if (rv) {
+ _rv = sms_decode(pdu, pdu_len, buf + 1, EOS_NET_SIZE_BUF - 1);
+ if (_rv < 0) {
eos_net_free(buf);
continue;
}
- eos_net_send(EOS_NET_MTYPE_CELL, buf, len + 1);
+ buf_len = _rv;
+ eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1);
} while (1);
eos_modem_give();
@@ -227,16 +276,26 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b
case EOS_CELL_MTYPE_SMS_MSG: {
char b[4];
- rv = sms_encode(buffer, buf_len);
- if (rv) return;
+ char *pdu = _pdu_in;
+ size_t pdu_size = sizeof(_pdu_in);
+ size_t pdu_len;
+ ssize_t _rv;
+
+ _rv = sms_encode(buffer, buf_len, pdu, pdu_size);
+ if (_rv < 0) return;
- rv = snprintf(cmd, sizeof(cmd), "AT+CMGS=%d\r", pdu_len / 2);
- if ((rv < 0) || (rv >= sizeof(cmd))) return;
+ pdu_len = _rv;
+ if (pdu_size < pdu_len + 2) return;
+ pdu[pdu_len] = CTRL_Z;
+ pdu[pdu_len + 1] = '\0';
+
+ rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CMGS=%d\r", pdu_len / 2);
+ if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return;
rv = eos_modem_take(1000);
if (rv) return;
- at_cmd(cmd);
+ at_cmd(at_cmd_buf);
// wait for: '> ' (0d 0a 3e 20)
eos_modem_read(b, 4, 1000);
at_cmd(pdu);
@@ -250,10 +309,16 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b
}
static void sms_received_handler(char *urc, regmatch_t m[]) {
+ char cmd[32];
unsigned char *buf;
- uint16_t len;
+ uint16_t buf_len;
int ref, rv;
+ char *pdu = _pdu_out;
+ size_t pdu_size = sizeof(_pdu_out);
+ size_t pdu_len;
+ ssize_t _rv;
+
sscanf(urc + m[1].rm_so, "%d", &ref);
rv = snprintf(cmd, sizeof(cmd), "AT+CMGR=%d\r", ref);
@@ -264,7 +329,7 @@ static void sms_received_handler(char *urc, regmatch_t m[]) {
rv = at_expect("^\\+CMGR: [0-9],.*,[0-9]+$", "^ERROR", 1000);
if (rv) return;
- rv = eos_modem_readln(pdu, sizeof(pdu), 1000);
+ rv = eos_modem_readln(pdu, pdu_size, 1000);
if (rv) return;
pdu_len = strlen(pdu);
@@ -273,13 +338,14 @@ static void sms_received_handler(char *urc, regmatch_t m[]) {
buf = eos_net_alloc();
buf[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_MSG;
- rv = sms_decode(buf + 1, &len);
- if (rv) {
+ _rv = sms_decode(pdu, pdu_len, buf + 1, EOS_NET_SIZE_BUF - 1);
+ if (_rv < 0) {
eos_net_free(buf);
return;
}
- eos_net_send(EOS_NET_MTYPE_CELL, buf, len + 1);
+ buf_len = _rv;
+ eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1);
}
void eos_cell_sms_init(void) {