diff options
Diffstat (limited to 'fw/esp32/components/eos/cell_sms.c')
-rw-r--r-- | fw/esp32/components/eos/cell_sms.c | 340 |
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) { |