mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-17 16:36:03 +08:00
1.新增esp-idf设备端sdk
This commit is contained in:
66
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/CMakeLists.txt
Normal file
66
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/CMakeLists.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
set(COMPONENT_PRIV_INCLUDEDIRS
|
||||
iotkit-embedded/coap_server/CoAPPacket
|
||||
iotkit-embedded/coap_server/server
|
||||
iotkit-embedded/dev_bind/impl
|
||||
iotkit-embedded/dev_bind/impl/os
|
||||
iotkit-embedded/dev_bind/impl/awss_reset
|
||||
iotkit-embedded/wifi_provision/dev_ap
|
||||
iotkit-embedded/wifi_provision/frameworks
|
||||
iotkit-embedded/wifi_provision/frameworks/aplist
|
||||
iotkit-embedded/wifi_provision/frameworks/ieee80211
|
||||
iotkit-embedded/wifi_provision/frameworks/statics
|
||||
iotkit-embedded/wifi_provision/frameworks/utils
|
||||
iotkit-embedded/wifi_provision/p2p
|
||||
iotkit-embedded/wifi_provision/phone_ap
|
||||
iotkit-embedded/wifi_provision/router_ap
|
||||
iotkit-embedded/wifi_provision/smartconfig
|
||||
iotkit-embedded/wifi_provision/zero_config)
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS
|
||||
conn_mgr
|
||||
iotkit-embedded/coap_server
|
||||
iotkit-embedded/dev_bind
|
||||
iotkit-embedded/dev_model
|
||||
iotkit-embedded/dev_sign
|
||||
iotkit-embedded/dynamic_register
|
||||
iotkit-embedded/mqtt
|
||||
iotkit-embedded/ota
|
||||
iotkit-embedded/infra
|
||||
iotkit-embedded/wifi_provision
|
||||
iotkit-embedded
|
||||
wrappers)
|
||||
|
||||
# Edit following two lines to set component requirements (see docs)
|
||||
set(COMPONENT_REQUIRES "nvs_flash" "app_update" "esp-tls")
|
||||
set(COMPONENT_PRIV_REQUIRES )
|
||||
|
||||
set(COMPONENT_SRCDIRS
|
||||
conn_mgr
|
||||
iotkit-embedded/certs
|
||||
iotkit-embedded/dev_bind/impl
|
||||
iotkit-embedded/dev_bind/impl/os
|
||||
iotkit-embedded/dev_bind/impl/awss_reset
|
||||
iotkit-embedded/dev_model
|
||||
iotkit-embedded/dev_reset
|
||||
iotkit-embedded/dev_sign
|
||||
iotkit-embedded/dynamic_register
|
||||
iotkit-embedded/infra
|
||||
iotkit-embedded/mqtt
|
||||
iotkit-embedded/ota
|
||||
iotkit-embedded/wifi_provision/dev_ap
|
||||
iotkit-embedded/wifi_provision/frameworks
|
||||
iotkit-embedded/wifi_provision/frameworks/aplist
|
||||
iotkit-embedded/wifi_provision/frameworks/ieee80211
|
||||
iotkit-embedded/wifi_provision/frameworks/statics
|
||||
iotkit-embedded/wifi_provision/frameworks/utils
|
||||
iotkit-embedded/wifi_provision/p2p
|
||||
iotkit-embedded/wifi_provision/phone_ap
|
||||
iotkit-embedded/wifi_provision/router_ap
|
||||
iotkit-embedded/wifi_provision/smartconfig
|
||||
iotkit-embedded/wifi_provision/zero_config
|
||||
iotkit-embedded/coap_server/CoAPPacket
|
||||
iotkit-embedded/coap_server/server
|
||||
wrappers)
|
||||
|
||||
register_component()
|
||||
component_compile_options(-DAUTH_MODE_CERT)
|
||||
143
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/Kconfig
Normal file
143
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/Kconfig
Normal file
@@ -0,0 +1,143 @@
|
||||
menu "iotkit embedded"
|
||||
|
||||
menu "Aliyun linkkit device version"
|
||||
|
||||
config LINKKIT_FIRMWARE_VERSION
|
||||
string "Device version"
|
||||
default "0.0.1"
|
||||
help
|
||||
aliyun linkkit device version
|
||||
endmenu
|
||||
|
||||
menu "Aliyun linkkit awss config"
|
||||
config AWSS_ENCRYPT_TYPE
|
||||
int "Get the security level of the `smartconfig` service"
|
||||
range 1 5
|
||||
default 3
|
||||
help
|
||||
Get the security level of the `smartconfig` service
|
||||
|
||||
config AWSS_CONN_ENCRYPT_TYPE
|
||||
int "Get Security level for wifi configuration with connection.Used for AP solution of router and App"
|
||||
range 3 5
|
||||
default 4
|
||||
help
|
||||
Get Security level for wifi configuration with connection.Used for AP solution of router and App
|
||||
|
||||
config AWSS_TIMEOUT_INTERVAL_MS
|
||||
int "Get the timeout period of the distribution service (`AWSS`), in milliseconds"
|
||||
range 0 1800000
|
||||
default 180000
|
||||
help
|
||||
Get the timeout period of the distribution service (`AWSS`), in milliseconds
|
||||
|
||||
config AWSS_CHANNELSCAN_INTERVAL_MS
|
||||
int "Get the length of time scanned on each channel (`channel`), in milliseconds"
|
||||
range 0 1000
|
||||
default 200
|
||||
help
|
||||
Get the length of time scanned on each channel (`channel`), in milliseconds
|
||||
endmenu
|
||||
|
||||
menu "Aliyun linkkit network config"
|
||||
config SUPPORT_TCP
|
||||
bool "Enable tcp connection"
|
||||
default n
|
||||
help
|
||||
Select this option to enable tcp connection
|
||||
|
||||
config TCP_ESTABLISH_TIMEOUT_MS
|
||||
int "Device tcp connection timeout wait time milliseconds"
|
||||
range 0 100000
|
||||
default 10000
|
||||
help
|
||||
Device tcp connection timeout wait time milliseconds
|
||||
|
||||
config TLS_ESTABLISH_TIMEOUT_MS
|
||||
int "Device tls connection timeout wait time milliseconds"
|
||||
range 0 100000
|
||||
default 10000
|
||||
help
|
||||
Device tls connection timeout wait time milliseconds
|
||||
endmenu
|
||||
|
||||
menu "Aliyun linkkit device model config"
|
||||
config DEVICE_MODEL_GATEWAY
|
||||
bool "Enable device model gateway"
|
||||
default n
|
||||
help
|
||||
Select this option to enable device model gateway
|
||||
endmenu
|
||||
|
||||
menu "Aliyun linkkit local control"
|
||||
config DEVICE_ALCS_ENABLE
|
||||
bool "Enable device local control"
|
||||
default n
|
||||
help
|
||||
Select this option to enable device local control
|
||||
endmenu
|
||||
|
||||
menu "Aliyun linkkit security OTA"
|
||||
config SUPPORT_SECURITY_OTA
|
||||
bool "Enable Security OTA"
|
||||
default n
|
||||
help
|
||||
Select this option to enable security ota
|
||||
endmenu
|
||||
|
||||
menu "Aliyun linkkit dynamic register"
|
||||
config DYNAMIC_REGISTER
|
||||
bool "Enable dynamic register"
|
||||
default y
|
||||
help
|
||||
Select this option to enable dynamic register
|
||||
endmenu
|
||||
|
||||
menu "Aliyun linkkit mqtt config"
|
||||
config MQTT_DIRECT
|
||||
bool "MQTT DIRECT"
|
||||
default y
|
||||
help
|
||||
Directly connect MQTT server without perform HTTP authenticate to another HTTP server ahead
|
||||
|
||||
Switching to "y" leads to connect MQTT server directly and MQTT_DIRECT included into CFLAGS
|
||||
Switching to "n" leads to legacy authenticate mode: connnect HTTP server first, then connect MQTT server afterwards
|
||||
endmenu
|
||||
|
||||
config HAL_SEM_MAX_COUNT
|
||||
int "The maximum count value that can be reached of the semaphore"
|
||||
default 255
|
||||
range 0 255
|
||||
help
|
||||
The recommended value of maximum count of the semaphore is 255
|
||||
|
||||
config HAL_SEM_INIT_COUNT
|
||||
int "The count value assigned to the semaphore when it is created"
|
||||
default 0
|
||||
range 0 10
|
||||
help
|
||||
The recommended value of count of the semaphore is 0
|
||||
config HAL_TLS_HANDSHAKE_TIMEOUT
|
||||
int "TLS Handsake Timeout"
|
||||
default 180
|
||||
range 0 65535
|
||||
help
|
||||
Default TLS handshake timeout to host in seconds
|
||||
config HAL_USE_CUSTOMER_AP_SSID
|
||||
bool "Enable use customer softap SSID"
|
||||
default n
|
||||
help
|
||||
Select this option to enable use customer softap SSID
|
||||
config AP_SSID_KEY
|
||||
string "AP SSID KV Key value"
|
||||
default "apssid"
|
||||
help
|
||||
The KV key value which store AP SSID
|
||||
|
||||
config USE_SOFTAP_CONFIG
|
||||
bool "Use softap config in smart light example"
|
||||
default n
|
||||
help
|
||||
smart light example will use softap config when enable this option. Otherwise use smartconfig.
|
||||
|
||||
endmenu
|
||||
65
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/component.mk
Normal file
65
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/component.mk
Normal file
@@ -0,0 +1,65 @@
|
||||
# Makefile
|
||||
COMPONENT_ADD_LDFLAGS += -u ota_pubn_buf
|
||||
COMPONENT_PRIV_INCLUDEDIRS := \
|
||||
iotkit-embedded/coap_server/CoAPPacket \
|
||||
iotkit-embedded/coap_server/server \
|
||||
iotkit-embedded/dev_bind/impl \
|
||||
iotkit-embedded/dev_bind/impl/os \
|
||||
iotkit-embedded/dev_bind/impl/awss_reset \
|
||||
iotkit-embedded/wifi_provision/dev_ap \
|
||||
iotkit-embedded/wifi_provision/frameworks \
|
||||
iotkit-embedded/wifi_provision/frameworks/aplist \
|
||||
iotkit-embedded/wifi_provision/frameworks/ieee80211 \
|
||||
iotkit-embedded/wifi_provision/frameworks/statics \
|
||||
iotkit-embedded/wifi_provision/frameworks/utils \
|
||||
iotkit-embedded/wifi_provision/p2p \
|
||||
iotkit-embedded/wifi_provision/phone_ap \
|
||||
iotkit-embedded/wifi_provision/router_ap \
|
||||
iotkit-embedded/wifi_provision/smartconfig \
|
||||
iotkit-embedded/wifi_provision/zero_config
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := \
|
||||
conn_mgr \
|
||||
iotkit-embedded/atm \
|
||||
iotkit-embedded/coap_server \
|
||||
iotkit-embedded/dev_bind \
|
||||
iotkit-embedded/dev_model \
|
||||
iotkit-embedded/dev_sign \
|
||||
iotkit-embedded/dynamic_register \
|
||||
iotkit-embedded/mqtt \
|
||||
iotkit-embedded/ota \
|
||||
iotkit-embedded/infra \
|
||||
iotkit-embedded/wifi_provision \
|
||||
iotkit-embedded \
|
||||
wrappers
|
||||
|
||||
COMPONENT_SRCDIRS := \
|
||||
conn_mgr \
|
||||
iotkit-embedded/atm \
|
||||
iotkit-embedded/certs \
|
||||
iotkit-embedded/dev_bind/impl \
|
||||
iotkit-embedded/dev_bind/impl/os \
|
||||
iotkit-embedded/dev_bind/impl/awss_reset \
|
||||
iotkit-embedded/dev_model \
|
||||
iotkit-embedded/dev_reset \
|
||||
iotkit-embedded/dev_sign \
|
||||
iotkit-embedded/dynamic_register \
|
||||
iotkit-embedded/infra \
|
||||
iotkit-embedded/mqtt \
|
||||
iotkit-embedded/ota \
|
||||
iotkit-embedded/wifi_provision/dev_ap \
|
||||
iotkit-embedded/wifi_provision/frameworks \
|
||||
iotkit-embedded/wifi_provision/frameworks/aplist \
|
||||
iotkit-embedded/wifi_provision/frameworks/ieee80211 \
|
||||
iotkit-embedded/wifi_provision/frameworks/statics \
|
||||
iotkit-embedded/wifi_provision/frameworks/utils \
|
||||
iotkit-embedded/wifi_provision/p2p \
|
||||
iotkit-embedded/wifi_provision/phone_ap \
|
||||
iotkit-embedded/wifi_provision/router_ap \
|
||||
iotkit-embedded/wifi_provision/smartconfig \
|
||||
iotkit-embedded/wifi_provision/zero_config \
|
||||
iotkit-embedded/coap_server/CoAPPacket \
|
||||
iotkit-embedded/coap_server/server \
|
||||
wrappers
|
||||
|
||||
CFLAGS += -Wno-char-subscripts
|
||||
@@ -0,0 +1,87 @@
|
||||
# 量产说明
|
||||
aliyun 在使用一机一密的情况下,需要在每个设备上烧写与设备对应的 ProductKey、ProductSecret、DeviceName、DeviceSecret。
|
||||
|
||||
为了使烧录和软件读取流程尽量简化,我们将使用 IDF 的 NVS 分区功能,将 ProductKey、ProductSecret、DeviceName、DeviceSecret 信息通过 NVS 分区生成工具或量产工具生成对应的 NVS 分区,该分区中利用 NVS 结构保存了 ProductKey、ProductSecret、DeviceName、DeviceSecret 的键值对。生成后的 NVS 分区 bin 可以通过 esptool 或其他烧写工具直接烧录到 NVS 分区对应的起始扇区,partition 分区表中指明了该 NVS 分区的起始地址。软件可以通过 NVS 相关接口读取到 ProductKey、ProductSecret、DeviceName、DeviceSecret 的具体值。
|
||||
|
||||
请参照 partitions_esp32.csv 和 partitions_esp8266.csv 中 fctry 的起始地址进行烧录,也可根据实际项目对 partitions 进行调整,但一定要保证 partitons 中 fctry 的实际地址与烧录地址保持吻合。
|
||||
|
||||
关于 NVS、NVS 分区生成工具、量产工具,请参考:
|
||||
- [NVS](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/nvs_flash.html)
|
||||
- [NVS 分区生成工具](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/nvs_partition_gen.html)
|
||||
- [量产工具](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/mass_mfg.html)
|
||||
|
||||
## 单个 bin 生成
|
||||
在调试过程中,建议使用该方式。
|
||||
|
||||
mass_mfg 目录中有一参考配置:single_mfg_config.csv,请拷贝成自己的配置文件,如 my_single_mfg_config.csv。
|
||||
```
|
||||
cp single_mfg_config.csv my_single_mfg_config.csv
|
||||
```
|
||||
|
||||
使用自己的 ProductKey、ProductSecret、DeviceName、DeviceSecret 对 my_single_mfg_config.csv 进行修改:
|
||||
```
|
||||
key,type,encoding,value
|
||||
aliyun-key,namespace,,
|
||||
DeviceName,data,string,config
|
||||
DeviceSecret,data,string,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh
|
||||
ProductKey,data,string,a10BnLLzGv4
|
||||
ProductSecret,data,string,pVfLpS1u3A9JM0go
|
||||
```
|
||||
|
||||
将 config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go 修改为你对应的值。
|
||||
|
||||
修改完成后,使用如下命令生成对应的 NVS 分区:
|
||||
```
|
||||
$IDF_PATH/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py --input single_mfg_config.csv --output single_mfg.bin --size 0x4000
|
||||
python nvs_partition_gen.py generate single_mfg_config.csv single_mfg.bin 0x4000
|
||||
```
|
||||
如针对 esp8266 平台,请使用如下命令:
|
||||
```
|
||||
$IDF_PATH/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py --input my_single_mfg_config.csv --output my_single_mfg.bin --size 0x4000
|
||||
```
|
||||
> 说明:esp8266 的 NVS 格式当前为 v1, 默认已设置。
|
||||
|
||||
可以使用 esptool 工具将生成的包含秘钥的 NVS 分区烧入对应的 sector,针对 example 中默认提供的 partitions,esp32 和 esp8266 将烧写到不同的分区,其中 esp32 的默认烧录地址为 0x210000,esp8266 的默认烧录地址为 0x100000。
|
||||
|
||||
针对 esp32:
|
||||
```
|
||||
$IDF_PATH/components/esptool_py/esptool/esptool.py write_flash 0x210000 my_single_mfg.bin
|
||||
```
|
||||
|
||||
针对 esp8266:
|
||||
```
|
||||
$IDF_PATH/components/esptool_py/esptool/esptool.py --port /dev/ttyUSB0 write_flash 0x100000 my_single_mfg.bin
|
||||
```
|
||||
|
||||
> 注,当前 esp32 默认使用 4MB 的模组,esp8266 默认使用 2MB 的模组,如使用其他大小的 Flash,请适当调整 partitions 分区表,并确认烧写地址。
|
||||
|
||||
## 多个 bin 批量生成
|
||||
量产过程中如采用以上方法单个生成对应的 NVS 分区会很繁琐,因此采用 IDF 中的量产工具,该量产工具也是基于 NVS 分区生成工具的扩充。
|
||||
|
||||
mass_mfg 目录中提供了一套参考的配置,其中 multipule_mfg_config.csv 为参数区配置文件,已做好针对 aliyun 的配置,用户无需修改,multipule_mfg_values.csv 中可以包含所有需要生成 NVS 分区的 ProductKey、ProductSecret、DeviceName、DeviceSecret 信息,请将 multipule_mfg_values.csv 复制为 my_multipule_mfg_values.csv 并对该文件进行修改,包含所有希望用于量产的 ProductKey、ProductSecret、DeviceName、DeviceSecret 信息。
|
||||
|
||||
my_multipule_mfg_values.csv 中内容如下:
|
||||
```
|
||||
id,DeviceName,DeviceSecret,ProductKey,ProductSecret
|
||||
1,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
|
||||
2,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
|
||||
3,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
|
||||
```
|
||||
|
||||
每一行代表了一组秘钥信息,第一列的为 id 信息,不会生成到对应的 NVS 分区中,仅用作标号。
|
||||
|
||||
采用如下命令批量生成 NVS 分区。
|
||||
|
||||
针对 esp32:
|
||||
```
|
||||
$IDF_PATH/tools/mass_mfg/mfg_gen.py --conf multipule_mfg_config.csv --values my_multipule_mfg_values.csv --prefix Fan --size 0x4000
|
||||
```
|
||||
|
||||
针对 esp8266:
|
||||
```
|
||||
$IDF_PATH/tools/mass_mfg/mfg_gen.py --conf multipule_mfg_config.csv --values my_multipule_mfg_values.csv --prefix Fan --size 0x4000 --version v1
|
||||
```
|
||||
|
||||
其中 --prefix 为生成的批量文件的前缀名称,可以修改为所需要的产品名称。执行完成后,会在当前目录下生成一 bin 目录,里面保持了所有可用于量产的 NVS 分区 bin。
|
||||
|
||||
> 注,当前不知道 aliyun 能否批量导出 ProductKey、ProductSecret、DeviceName、DeviceSecret,如有需要,可以编写特定脚本来生成 my_multipule_mfg_values.csv。
|
||||
@@ -0,0 +1,5 @@
|
||||
aliyun-key,namespace,
|
||||
DeviceName,data,string
|
||||
DeviceSecret,data,string
|
||||
ProductKey,data,string
|
||||
ProductSecret,data,string
|
||||
|
@@ -0,0 +1,4 @@
|
||||
id,DeviceName,DeviceSecret,ProductKey,ProductSecret
|
||||
1,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
|
||||
2,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
|
||||
3,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
|
||||
|
@@ -0,0 +1,6 @@
|
||||
key,type,encoding,value
|
||||
aliyun-key,namespace,,
|
||||
DeviceName,data,string,DCDA0C11FEBC
|
||||
DeviceSecret,data,string,8eb157145f057600459e9b7245beb59f
|
||||
ProductKey,data,string,a1LCAxGhf7h
|
||||
ProductSecret,data,string,c119juI2ruCDg3A7
|
||||
|
415
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.c
Normal file
415
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.c
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
#include "lwip/apps/sntp.h"
|
||||
|
||||
#include "wifi_provision_api.h"
|
||||
#include "dm_wrapper.h"
|
||||
|
||||
#include "conn_mgr.h"
|
||||
|
||||
static const char *TAG = "conn_mgr";
|
||||
|
||||
static system_event_cb_t hal_wifi_system_cb;
|
||||
|
||||
static esp_err_t conn_mgr_wifi_connect(void)
|
||||
{
|
||||
wifi_config_t wifi_config = {0};
|
||||
int ssid_len = sizeof(wifi_config.sta.ssid);
|
||||
int password_len = sizeof(wifi_config.sta.password);
|
||||
|
||||
int ret = HAL_Kv_Get(STA_SSID_KEY, wifi_config.sta.ssid, &ssid_len);
|
||||
ESP_LOGI(TAG, "HAL_Kv_Get STA_SSID_KEY: %s ", wifi_config.sta.ssid);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to get stored SSID");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Even if the password is not found, it is not an error, as it could be an open network */
|
||||
ret = HAL_Kv_Get(STA_PASSWORD_KEY, wifi_config.sta.password, &password_len);
|
||||
ESP_LOGI(TAG, "HAL_Kv_Get STA_PASSWORD_KEY: %s ", wifi_config.sta.password);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to get stored Password");
|
||||
password_len = 0;
|
||||
}
|
||||
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
|
||||
esp_wifi_start();
|
||||
esp_wifi_connect();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t conn_mgr_save_wifi_config(void)
|
||||
{
|
||||
wifi_config_t wifi_config = {0};
|
||||
|
||||
esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_config);
|
||||
|
||||
/* Do not save hotspot or router APs. */
|
||||
if (strcmp((char *)(wifi_config.sta.ssid), HOTSPOT_AP) == 0 ||
|
||||
strcmp((char *)(wifi_config.sta.ssid), ROUTER_AP) == 0) {
|
||||
ESP_LOGI(TAG, "Do not save hotspot or router APs: %s", wifi_config.sta.ssid);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int ret = HAL_Kv_Set(STA_SSID_KEY, wifi_config.sta.ssid, sizeof(wifi_config.sta.ssid), 0);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s key store failed with %d", STA_SSID_KEY, ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Password may be NULL. Save, only if it is given */
|
||||
if (wifi_config.sta.password[0] != 0) {
|
||||
ret = HAL_Kv_Set(STA_PASSWORD_KEY, wifi_config.sta.password, sizeof(wifi_config.sta.password), 0);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s key store failed with %d", STA_PASSWORD_KEY, ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t conn_mgr_obtain_time(void)
|
||||
{
|
||||
static bool get_time_flag = false;
|
||||
if (get_time_flag) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, "ntp1.aliyun.com");
|
||||
sntp_setservername(1, "ntp2.aliyun.com");
|
||||
sntp_setservername(2, "ntp3.aliyun.com");
|
||||
sntp_init();
|
||||
|
||||
time_t now = 0;
|
||||
struct tm timeinfo = { 0 };
|
||||
int sntp_retry_cnt = 0;
|
||||
int sntp_retry_time = 0;
|
||||
while (1) {
|
||||
for (int32_t i = 0; (i < (SNTP_RECV_TIMEOUT / 100)) && timeinfo.tm_year < (2019 - 1900); i ++) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
}
|
||||
|
||||
if (timeinfo.tm_year < (2019 - 1900) && sntp_retry_cnt < (SNTP_RECV_TIMEOUT / 100)) {
|
||||
sntp_retry_time = SNTP_RECV_TIMEOUT << sntp_retry_cnt;
|
||||
|
||||
if (SNTP_RECV_TIMEOUT << (sntp_retry_cnt + 1) < SNTP_RETRY_TIMEOUT_MAX) {
|
||||
sntp_retry_cnt ++;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG,"SNTP get time failed, retry after %d ms\n", sntp_retry_time);
|
||||
vTaskDelay(sntp_retry_time / portTICK_RATE_MS);
|
||||
} else {
|
||||
ESP_LOGI(TAG,"SNTP get time success\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
get_time_flag = true;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t conn_mgr_wifi_event_loop_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
system_event_info_t *info = &event->event_info;
|
||||
switch (event->event_id) {
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
conn_mgr_save_wifi_config();
|
||||
#ifdef CONFIG_ESP_TLS_USING_WOLFSSL
|
||||
conn_mgr_obtain_time();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP8266
|
||||
if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) {
|
||||
/*Switch to 802.11 bgn mode */
|
||||
esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N);
|
||||
}
|
||||
#endif
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/** The application loop event handle */
|
||||
if (hal_wifi_system_cb) {
|
||||
hal_wifi_system_cb(ctx, event);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void conn_mgr_register_wifi_event(system_event_cb_t cb)
|
||||
{
|
||||
hal_wifi_system_cb = cb;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_reset_wifi_config(void)
|
||||
{
|
||||
HAL_Kv_Del(STA_SSID_KEY);
|
||||
HAL_Kv_Del(STA_PASSWORD_KEY);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_init_wifi_config(void)
|
||||
{
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = CONFIG_ESP_WIFI_SSID,
|
||||
.password = CONFIG_ESP_WIFI_PASSWORD,
|
||||
},
|
||||
};
|
||||
int ret = HAL_Kv_Set(STA_SSID_KEY, wifi_config.sta.ssid, sizeof(wifi_config.sta.ssid), 0);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s key store failed with %d", STA_SSID_KEY, ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ret = HAL_Kv_Set(STA_PASSWORD_KEY, wifi_config.sta.password, sizeof(wifi_config.sta.password), 0);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s key store failed with %d", STA_PASSWORD_KEY, ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t conn_mgr_is_configured(bool *configured)
|
||||
{
|
||||
if (!configured) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*configured = false;
|
||||
|
||||
int ssid_len = 32;
|
||||
uint8_t ssid[32];
|
||||
|
||||
int ret = HAL_Kv_Get(STA_SSID_KEY, ssid, &ssid_len);
|
||||
|
||||
if (ret == ESP_OK && ssid_len) {
|
||||
*configured = true;
|
||||
ESP_LOGI(TAG, "Found ssid %s", ssid);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_set_wifi_config_ext(const uint8_t *ssid, size_t ssid_len, const uint8_t *password, size_t password_len)
|
||||
{
|
||||
wifi_config_t wifi_config = {0};
|
||||
|
||||
if (!ssid || ssid_len > sizeof(wifi_config.sta.ssid) || password_len > sizeof(wifi_config.sta.password))
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
|
||||
memcpy(wifi_config.sta.ssid, ssid, ssid_len);
|
||||
if (password) {
|
||||
memcpy(wifi_config.sta.password, password, password_len);
|
||||
}
|
||||
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
|
||||
|
||||
conn_mgr_save_wifi_config();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_get_wifi_config(wifi_config_t *wifi_cfg)
|
||||
{
|
||||
return esp_wifi_get_config(ESP_IF_WIFI_STA, wifi_cfg);
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_init(void)
|
||||
{
|
||||
extern esp_err_t HAL_Kv_Init(void);
|
||||
HAL_Kv_Init();
|
||||
|
||||
tcpip_adapter_init();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_event_loop_init(conn_mgr_wifi_event_loop_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_start(void)
|
||||
{
|
||||
bool ret = true;
|
||||
bool configured = false;
|
||||
uint8_t mode = 0;
|
||||
int mode_len = sizeof(uint8_t);
|
||||
conn_sc_mode_t awss_mode = CONN_SC_ZERO_MODE;
|
||||
|
||||
// Let's find out if the device is configured.
|
||||
if (conn_mgr_is_configured(&configured) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Get SC mode and decide to start which awss service
|
||||
HAL_Kv_Get(SC_MODE, &mode, &mode_len);
|
||||
if (mode_len && mode == CONN_SOFTAP_MODE) {
|
||||
ESP_LOGI(TAG, "CONN_SOFTAP_MODE");
|
||||
awss_mode = CONN_SOFTAP_MODE;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "mode: %d ", mode);
|
||||
}
|
||||
|
||||
// If the device is not yet configured, start awss service.
|
||||
if (!configured) {
|
||||
do {
|
||||
if (awss_config_press() != 0) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
if (awss_mode == CONN_SOFTAP_MODE) {
|
||||
if (awss_dev_ap_start() != 0) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (awss_start() != 0) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
} else {
|
||||
if (conn_mgr_wifi_connect() != ESP_OK) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret == true ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_stop(void)
|
||||
{
|
||||
bool ret = true;
|
||||
bool configured = false;
|
||||
uint8_t mode = 0;
|
||||
int mode_len = sizeof(uint8_t);
|
||||
conn_sc_mode_t awss_mode = CONN_SC_ZERO_MODE;
|
||||
|
||||
// Let's find out if the device is configured.
|
||||
if (conn_mgr_is_configured(&configured) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Get SC mode and decide to start which awss service
|
||||
HAL_Kv_Get(SC_MODE, &mode, &mode_len);
|
||||
if (mode_len && mode == CONN_SOFTAP_MODE) {
|
||||
awss_mode = CONN_SOFTAP_MODE;
|
||||
}
|
||||
|
||||
// If the device is not yet configured, stop awss service.
|
||||
if (!configured) {
|
||||
if (awss_mode == CONN_SOFTAP_MODE) {
|
||||
if (awss_dev_ap_stop() != 0) {
|
||||
ret = false;
|
||||
}
|
||||
} else {
|
||||
if (awss_stop() != 0) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret == true ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_set_ap_ssid(uint8_t *ssid, int len)
|
||||
{
|
||||
int ret = ESP_FAIL;
|
||||
uint8_t ssid_kv[32] = {0};
|
||||
int len_kv = 32;
|
||||
|
||||
if (!ssid || !len) {
|
||||
ESP_LOGI(TAG, "input ssid and len error");
|
||||
return ret;
|
||||
}
|
||||
ret = HAL_Kv_Get(AP_SSID_KEY, ssid_kv, &len_kv);
|
||||
if (ret == ESP_OK && len_kv == len) {
|
||||
if (!memcmp(ssid, ssid_kv, len)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ret = HAL_Kv_Set(AP_SSID_KEY, ssid, len, 0);
|
||||
ESP_LOGI(TAG, "%s %s", __FUNCTION__, (ret == ESP_OK) ? "success" : "fail");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t conn_mgr_set_sc_mode(uint8_t mode)
|
||||
{
|
||||
int ret = ESP_FAIL;
|
||||
uint8_t mode_kv = 0;
|
||||
int len_kv = sizeof(uint8_t);
|
||||
|
||||
ret = HAL_Kv_Get(SC_MODE, &mode_kv, &len_kv);
|
||||
if (ret == ESP_OK) {
|
||||
if (mode == mode_kv) {
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ret = HAL_Kv_Set(SC_MODE, &mode, sizeof(uint8_t), 0);
|
||||
ESP_LOGI(TAG, "%s %s", __FUNCTION__, (ret == ESP_OK) ? "success" : "fail");
|
||||
|
||||
return ret;
|
||||
}
|
||||
149
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.h
Normal file
149
sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_event_loop.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HOTSPOT_AP "aha"
|
||||
#define ROUTER_AP "adha"
|
||||
#define STA_SSID_KEY "stassid"
|
||||
#define STA_PASSWORD_KEY "pswd"
|
||||
#define AP_SSID_KEY CONFIG_AP_SSID_KEY
|
||||
#define SC_MODE "scmode"
|
||||
|
||||
typedef enum {
|
||||
CONN_SC_ZERO_MODE = 1,
|
||||
CONN_SOFTAP_MODE = 2,
|
||||
} conn_sc_mode_t;
|
||||
|
||||
/**
|
||||
* @brief register wifi event handler
|
||||
*
|
||||
* @param cb wifi event handler
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void conn_mgr_register_wifi_event(system_event_cb_t cb);
|
||||
|
||||
/**
|
||||
* @brief reset the stored router info, include ssid & password
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_reset_wifi_config(void);
|
||||
esp_err_t conn_mgr_init_wifi_config(void);
|
||||
|
||||
/**
|
||||
* @brief connect wifi with configure information
|
||||
*
|
||||
* This will initiate connection to the given Wi-Fi configure information
|
||||
*
|
||||
* @param ssid Pointer to the target network SSID string
|
||||
* @param ssid_len Length of the above SSID
|
||||
* @param password Pointer to the targer network Password string. Can be NULL for open networks.
|
||||
* @param password_len Length of the password
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_set_wifi_config_ext(const uint8_t *ssid, size_t ssid_len, const uint8_t *password, size_t password_len);
|
||||
|
||||
/**
|
||||
* @brief get wifi configure information
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_get_wifi_config(wifi_config_t *wifi_cfg);
|
||||
|
||||
/**
|
||||
* @brief init the connection management module
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_init(void);
|
||||
|
||||
/**
|
||||
* @brief start the connection management module
|
||||
*
|
||||
* If the device is configured, the device will connect to the router which is configured.
|
||||
* If the device is not configured, the device will start awss service.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_start(void);
|
||||
|
||||
/**
|
||||
* @brief stop the connection management module
|
||||
*
|
||||
* If the device is configured, the device keep connect to the router which is configured.
|
||||
* If the device is not configured, the device will stop awss service.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_stop(void);
|
||||
|
||||
/**
|
||||
* @brief set softap ssid to KV
|
||||
*
|
||||
* @param ssid Pointer to the softap SSID string
|
||||
* @param len Length of the above SSID
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_set_ap_ssid(uint8_t *ssid, int len);
|
||||
|
||||
/**
|
||||
* @brief set wifi distribution network mode to KV
|
||||
*
|
||||
* If mode is 1, means support smartconfig and zero-config
|
||||
* If mode is 2, means support softap config
|
||||
* @param mode Value of the sc mode
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : OK
|
||||
* - others : fail
|
||||
*/
|
||||
esp_err_t conn_mgr_set_sc_mode(uint8_t mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
const char *iotx_ca_crt = \
|
||||
{
|
||||
\
|
||||
"-----BEGIN CERTIFICATE-----\r\n"
|
||||
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n" \
|
||||
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n" \
|
||||
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\r\n" \
|
||||
"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n" \
|
||||
"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\r\n" \
|
||||
"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\r\n" \
|
||||
"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\r\n" \
|
||||
"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\r\n" \
|
||||
"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\r\n" \
|
||||
"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\r\n" \
|
||||
"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\r\n" \
|
||||
"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\r\n" \
|
||||
"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\r\n" \
|
||||
"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\r\n" \
|
||||
"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\r\n" \
|
||||
"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\r\n" \
|
||||
"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\r\n" \
|
||||
"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\r\n" \
|
||||
"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n" \
|
||||
"-----END CERTIFICATE-----"
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "Cloud_CoAPNetwork.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifndef CLOUD__COAP_EXPORT_H__
|
||||
#define CLOUD__COAP_EXPORT_H__
|
||||
|
||||
/* #define COAP_DTLS_SUPPORT */
|
||||
typedef CoAPMsgOption Cloud_CoAPMsgOption;
|
||||
typedef CoAPMessageCode Cloud_CoAPMessageCode;
|
||||
typedef CoAPMessage Cloud_CoAPMessage ;
|
||||
#define COAP_OPTION_SEQ 2089
|
||||
|
||||
typedef void (*Cloud_CoAPRespMsgHandler)(void *data, void *message);
|
||||
|
||||
typedef struct {
|
||||
void *user;
|
||||
unsigned short msgid;
|
||||
char acked;
|
||||
unsigned char tokenlen;
|
||||
unsigned char token[8];
|
||||
unsigned char retrans_count;
|
||||
unsigned short timeout;
|
||||
unsigned short timeout_val;
|
||||
unsigned char *message;
|
||||
unsigned int msglen;
|
||||
Cloud_CoAPRespMsgHandler resp;
|
||||
struct list_head sendlist;
|
||||
} Cloud_CoAPSendNode;
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned char count;
|
||||
unsigned char maxcount;
|
||||
struct list_head sendlist;
|
||||
} Cloud_CoAPSendList;
|
||||
|
||||
|
||||
typedef void (*Cloud_CoAPEventNotifier)(unsigned int event, void *p_message);
|
||||
typedef struct {
|
||||
char *url;
|
||||
unsigned char maxcount; /*list maximal count*/
|
||||
unsigned int waittime;
|
||||
Cloud_CoAPEventNotifier notifier;
|
||||
} Cloud_CoAPInitParam;
|
||||
|
||||
typedef struct {
|
||||
unsigned short message_id;
|
||||
coap_network_t network;
|
||||
Cloud_CoAPEventNotifier notifier;
|
||||
unsigned char *sendbuf;
|
||||
unsigned char *recvbuf;
|
||||
Cloud_CoAPSendList list;
|
||||
unsigned int waittime;
|
||||
} Cloud_CoAPContext;
|
||||
|
||||
#define COAP_TRC(...) log_debug("coap_cloud", __VA_ARGS__)
|
||||
#define COAP_DUMP(...) log_debug("coap_cloud", __VA_ARGS__)
|
||||
#define COAP_DEBUG(...) log_debug("coap_cloud", __VA_ARGS__)
|
||||
#define COAP_INFO(...) log_info("coap_cloud", __VA_ARGS__)
|
||||
#define COAP_WRN(...) log_warning("coap_cloud", __VA_ARGS__)
|
||||
#define COAP_ERR(...) log_err("coap_cloud", __VA_ARGS__)
|
||||
|
||||
Cloud_CoAPContext *Cloud_CoAPContext_create(Cloud_CoAPInitParam *param);
|
||||
void Cloud_CoAPContext_free(Cloud_CoAPContext *p_ctx);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include "Cloud_CoAPExport.h"
|
||||
|
||||
#ifndef __COAP_HANDLE_MSG_H__
|
||||
#define __COAP_HANDLE_MSG_H__
|
||||
|
||||
int Cloud_CoAPStrOption_add(Cloud_CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short datalen);
|
||||
|
||||
|
||||
int Cloud_CoAPUintOption_add(Cloud_CoAPMessage *message, unsigned short optnum,
|
||||
unsigned int data);
|
||||
|
||||
unsigned short Cloud_CoAPMessageId_gen(Cloud_CoAPContext *context);
|
||||
|
||||
int Cloud_CoAPMessageId_set(Cloud_CoAPMessage *message, unsigned short msgid);
|
||||
|
||||
int Cloud_CoAPMessageType_set(Cloud_CoAPMessage *message, unsigned char type);
|
||||
|
||||
int Cloud_CoAPMessageCode_set(Cloud_CoAPMessage *message, Cloud_CoAPMessageCode code);
|
||||
|
||||
int Cloud_CoAPMessageToken_set(Cloud_CoAPMessage *message, unsigned char *token,
|
||||
unsigned char tokenlen);
|
||||
|
||||
int Cloud_CoAPMessageUserData_set(Cloud_CoAPMessage *message, void *userdata);
|
||||
|
||||
int Cloud_CoAPMessagePayload_set(Cloud_CoAPMessage *message, unsigned char *payload,
|
||||
unsigned short payloadlen);
|
||||
|
||||
int Cloud_CoAPMessageHandler_set(Cloud_CoAPMessage *message, Cloud_CoAPRespMsgHandler handler);
|
||||
|
||||
int Cloud_CoAPMessage_init(Cloud_CoAPMessage *message);
|
||||
|
||||
int Cloud_CoAPMessage_destory(Cloud_CoAPMessage *message);
|
||||
|
||||
int Cloud_CoAPMessage_send(Cloud_CoAPContext *context, Cloud_CoAPMessage *message);
|
||||
|
||||
int Cloud_CoAPMessage_recv(Cloud_CoAPContext *context, unsigned int timeout, int readcount);
|
||||
|
||||
int Cloud_CoAPMessage_cycle(Cloud_CoAPContext *context);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef COAP_TRANSPORT_H__
|
||||
#define COAP_TRANSPORT_H__
|
||||
|
||||
typedef enum {
|
||||
COAP_ENDPOINT_NOSEC = 0,
|
||||
COAP_ENDPOINT_DTLS,
|
||||
COAP_ENDPOINT_PSK,
|
||||
} coap_endpoint_type;
|
||||
|
||||
|
||||
typedef struct {
|
||||
DTLSContext *context;
|
||||
} coap_remote_session_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int socket_id;
|
||||
coap_endpoint_type ep_type;
|
||||
void *context;
|
||||
} coap_network_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
coap_endpoint_type ep_type;
|
||||
unsigned char *p_ca_cert_pem;
|
||||
char *p_host;
|
||||
unsigned short port;
|
||||
} coap_network_init_t;
|
||||
|
||||
|
||||
unsigned int Cloud_CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t *p_network);
|
||||
|
||||
|
||||
unsigned int Cloud_CoAPNetwork_write(coap_network_t *p_network,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen);
|
||||
|
||||
int Cloud_CoAPNetwork_read(coap_network_t *network, unsigned char *data,
|
||||
unsigned int datalen, unsigned int timeout);
|
||||
|
||||
unsigned int Cloud_CoAPNetwork_deinit(coap_network_t *p_network);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __COAP_PLATFORM_OS_H__
|
||||
#define __COAP_PLATFORM_OS_H__
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define coap_malloc(size) LITE_malloc(size, MEM_MAGIC, "coap.cloud")
|
||||
#define coap_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define coap_malloc(size) HAL_Malloc(size)
|
||||
#define coap_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __COAP_DESERIALIZE_H__
|
||||
#define __COAP_DESERIALIZE_H__
|
||||
#include <stdio.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
int CoAPDeserialize_Header(CoAPMessage *msg, unsigned char *buf)
|
||||
{
|
||||
msg->header.version = ((buf[0] >> 6) & 0x03);
|
||||
msg->header.type = ((buf[0] >> 4) & 0x03);
|
||||
msg->header.tokenlen = (buf[0] & 0x0F);
|
||||
msg->header.code = buf[1];
|
||||
msg->header.msgid = buf[2] << 8;
|
||||
msg->header.msgid += buf[3];
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Token(CoAPMessage *msg, unsigned char *buf)
|
||||
{
|
||||
memcpy(msg->token, buf, msg->header.tokenlen);
|
||||
return msg->header.tokenlen;
|
||||
}
|
||||
|
||||
static int CoAPDeserialize_Option(CoAPMsgOption *option, unsigned char *buf, unsigned short *predeltas)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short optdelta = 0;
|
||||
unsigned short optlen = 0;
|
||||
unsigned short predelta = 0;
|
||||
|
||||
optdelta = (*ptr & 0xF0) >> 4;
|
||||
optlen = (*ptr & 0x0F);
|
||||
ptr++;
|
||||
|
||||
predelta = *predeltas;
|
||||
if (13 == optdelta) {
|
||||
predelta += 13 + *ptr;
|
||||
ptr ++;
|
||||
|
||||
} else if (14 == optdelta) {
|
||||
predelta += 269;
|
||||
predelta += (*ptr << 8);
|
||||
predelta += *(ptr + 1);
|
||||
ptr += 2;
|
||||
} else {
|
||||
predelta += optdelta;
|
||||
}
|
||||
option->num = predelta;
|
||||
|
||||
if (13 == optlen) {
|
||||
optlen = 13 + *ptr;
|
||||
ptr ++;
|
||||
} else if (14 == optlen) {
|
||||
optlen = 269;
|
||||
optlen += (*ptr << 8);
|
||||
optlen += *(ptr + 1);
|
||||
ptr += 2;
|
||||
}
|
||||
option->len = optlen;
|
||||
|
||||
option->val = ptr;
|
||||
*predeltas = option->num;
|
||||
|
||||
return (ptr - buf + option->len);
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Options(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
int index = 0;
|
||||
int count = 0;
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short len = 0;
|
||||
unsigned short optdeltas = 0;
|
||||
|
||||
msg->optcount = 0;
|
||||
while ((count < buflen) && (0xFF != *ptr)) {
|
||||
len = CoAPDeserialize_Option(&msg->options[index], ptr, &optdeltas);
|
||||
msg->optcount += 1;
|
||||
ptr += len;
|
||||
index ++;
|
||||
count += len;
|
||||
}
|
||||
|
||||
return (int)(ptr - buf);
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
if (0xFF == *ptr) {
|
||||
ptr ++;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
msg->payloadlen = buflen - 1;
|
||||
msg->payload = (unsigned char *)ptr;
|
||||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
int count = 0;
|
||||
int remlen = buflen;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
if (NULL == buf || NULL == msg) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (buflen < 4) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
/* Deserialize CoAP header. */
|
||||
count = CoAPDeserialize_Header(msg, ptr);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
/* Deserialize the token, if any. */
|
||||
count = CoAPDeserialize_Token(msg, ptr);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPDeserialize_Options(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
CoAPDeserialize_Payload(msg, ptr, remlen);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "ctype.h"
|
||||
#include "Cloud_CoAPPlatform.h"
|
||||
#include "Cloud_CoAPNetwork.h"
|
||||
#include "Cloud_CoAPExport.h"
|
||||
|
||||
#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */
|
||||
#define COAPS_DEFAULT_PORT 5684 /* CoAP default UDP port for secure transmission */
|
||||
|
||||
#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */
|
||||
#define COAP_DEFAULT_HOST_LEN 128
|
||||
#define COAP_DEFAULT_WAIT_TIME_MS 2000
|
||||
|
||||
unsigned int Cloud_CoAPUri_parse(char *p_uri, coap_endpoint_type *p_endpoint_type,
|
||||
char host[COAP_DEFAULT_HOST_LEN], unsigned short *port)
|
||||
{
|
||||
int len = 0;
|
||||
char *p = NULL, *q = NULL;
|
||||
if (NULL == p_uri || NULL == p_endpoint_type) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
COAP_DEBUG("The uri is %s", p_uri);
|
||||
len = strlen(p_uri);
|
||||
p = p_uri;
|
||||
q = (char *)COAP_DEFAULT_SCHEME;
|
||||
while (len && *q && tolower(*p) == *q) {
|
||||
++p;
|
||||
++q;
|
||||
--len;
|
||||
}
|
||||
|
||||
if (*q) {
|
||||
return COAP_ERROR_INVALID_URI;
|
||||
}
|
||||
if (tolower(*p) == 's') {
|
||||
++p;
|
||||
--len;
|
||||
*p_endpoint_type = COAP_ENDPOINT_DTLS;
|
||||
*port = COAPS_DEFAULT_PORT;
|
||||
} else if (*p == '-') {
|
||||
++p;
|
||||
--len;
|
||||
q = (char *)"psk";
|
||||
while (len && *q && tolower(*p) == *q) {
|
||||
++p;
|
||||
++q;
|
||||
--len;
|
||||
}
|
||||
if (*q) {
|
||||
return COAP_ERROR_INVALID_URI;
|
||||
}
|
||||
*p_endpoint_type = COAP_ENDPOINT_PSK;
|
||||
*port = COAP_DEFAULT_PORT;
|
||||
} else {
|
||||
*p_endpoint_type = COAP_ENDPOINT_NOSEC;
|
||||
*port = COAP_DEFAULT_PORT;
|
||||
}
|
||||
COAP_DEBUG("The endpoint type is: %d", *p_endpoint_type);
|
||||
|
||||
q = (char *)"://";
|
||||
while (len && *q && tolower(*p) == *q) {
|
||||
++p;
|
||||
++q;
|
||||
--len;
|
||||
}
|
||||
|
||||
if (*q) {
|
||||
return COAP_ERROR_INVALID_URI;
|
||||
}
|
||||
|
||||
q = p;
|
||||
while (len && *q != ':') {
|
||||
++q;
|
||||
--len;
|
||||
}
|
||||
if (p == q) {
|
||||
return COAP_ERROR_INVALID_URI;
|
||||
}
|
||||
|
||||
if (COAP_DEFAULT_HOST_LEN - 1 < (q - p)) {
|
||||
return COAP_ERROR_INVALID_URI;
|
||||
} else {
|
||||
memset(host, 0x00, COAP_DEFAULT_HOST_LEN);
|
||||
strncpy(host, p, q - p);
|
||||
}
|
||||
COAP_DEBUG("The host name is: %s", host);
|
||||
if (len && *q == ':') {
|
||||
p = ++q;
|
||||
--len;
|
||||
|
||||
while (len && isdigit(*q)) {
|
||||
++q;
|
||||
--len;
|
||||
}
|
||||
|
||||
if (p < q) {
|
||||
int uri_port = 0;
|
||||
|
||||
while (p < q) {
|
||||
uri_port = uri_port * 10 + (*p++ - '0');
|
||||
}
|
||||
|
||||
if (uri_port > 65535) {
|
||||
return COAP_ERROR_INVALID_URI;
|
||||
}
|
||||
*port = uri_port;
|
||||
}
|
||||
}
|
||||
COAP_DEBUG("The port is: %d", *port);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Cloud_CoAPContext *Cloud_CoAPContext_create(Cloud_CoAPInitParam *param)
|
||||
{
|
||||
unsigned int ret = COAP_SUCCESS;
|
||||
Cloud_CoAPContext *p_ctx = NULL;
|
||||
coap_network_init_t network_param;
|
||||
char host[COAP_DEFAULT_HOST_LEN] = {0};
|
||||
|
||||
memset(&network_param, 0x00, sizeof(coap_network_init_t));
|
||||
p_ctx = coap_malloc(sizeof(Cloud_CoAPContext));
|
||||
if (NULL == p_ctx) {
|
||||
COAP_ERR("malloc for coap context failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(p_ctx, 0, sizeof(Cloud_CoAPContext));
|
||||
p_ctx->message_id = 1;
|
||||
p_ctx->notifier = param->notifier;
|
||||
p_ctx->sendbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
|
||||
if (NULL == p_ctx->sendbuf) {
|
||||
COAP_ERR("not enough memory");
|
||||
goto err;
|
||||
}
|
||||
|
||||
p_ctx->recvbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
|
||||
if (NULL == p_ctx->recvbuf) {
|
||||
COAP_ERR("not enough memory");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (0 == param->waittime) {
|
||||
p_ctx->waittime = COAP_DEFAULT_WAIT_TIME_MS;
|
||||
} else {
|
||||
p_ctx->waittime = param->waittime;
|
||||
}
|
||||
|
||||
/*CoAP message send list*/
|
||||
INIT_LIST_HEAD(&p_ctx->list.sendlist);
|
||||
p_ctx->list.count = 0;
|
||||
p_ctx->list.maxcount = param->maxcount;
|
||||
|
||||
/*set the endpoint type by uri schema*/
|
||||
if (NULL != param->url) {
|
||||
ret = Cloud_CoAPUri_parse(param->url, &network_param.ep_type, host, &network_param.port);
|
||||
}
|
||||
|
||||
if (COAP_SUCCESS != ret) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_ENDPOINT_DTLS == network_param.ep_type) {
|
||||
extern const char *iotx_ca_crt;
|
||||
network_param.p_ca_cert_pem = (unsigned char *)iotx_ca_crt;
|
||||
}
|
||||
#endif
|
||||
if (COAP_ENDPOINT_NOSEC == network_param.ep_type
|
||||
|| COAP_ENDPOINT_PSK == network_param.ep_type) {
|
||||
network_param.p_ca_cert_pem = NULL;
|
||||
}
|
||||
network_param.p_host = host;
|
||||
|
||||
/*CoAP network init*/
|
||||
ret = Cloud_CoAPNetwork_init(&network_param, &p_ctx->network);
|
||||
|
||||
if (COAP_SUCCESS != ret) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
return p_ctx;
|
||||
err:
|
||||
if (NULL == p_ctx) {
|
||||
return p_ctx;
|
||||
}
|
||||
|
||||
if (NULL != p_ctx->recvbuf) {
|
||||
coap_free(p_ctx->recvbuf);
|
||||
p_ctx->recvbuf = NULL;
|
||||
}
|
||||
|
||||
if (NULL != p_ctx->sendbuf) {
|
||||
coap_free(p_ctx->sendbuf);
|
||||
p_ctx->sendbuf = NULL;
|
||||
}
|
||||
|
||||
coap_free(p_ctx);
|
||||
p_ctx = NULL;
|
||||
|
||||
return p_ctx;
|
||||
}
|
||||
|
||||
void Cloud_CoAPContext_free(Cloud_CoAPContext *p_ctx)
|
||||
{
|
||||
Cloud_CoAPSendNode *cur, *next;
|
||||
|
||||
if (NULL == p_ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cloud_CoAPNetwork_deinit(&p_ctx->network);
|
||||
|
||||
list_for_each_entry_safe(cur, next, &p_ctx->list.sendlist, sendlist, Cloud_CoAPSendNode) {
|
||||
if (NULL != cur) {
|
||||
if (NULL != cur->message) {
|
||||
coap_free(cur->message);
|
||||
cur->message = NULL;
|
||||
}
|
||||
coap_free(cur);
|
||||
cur = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != p_ctx->recvbuf) {
|
||||
coap_free(p_ctx->recvbuf);
|
||||
p_ctx->recvbuf = NULL;
|
||||
}
|
||||
|
||||
if (NULL != p_ctx->sendbuf) {
|
||||
coap_free(p_ctx->sendbuf);
|
||||
p_ctx->sendbuf = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (NULL != p_ctx) {
|
||||
coap_free(p_ctx);
|
||||
p_ctx = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "Cloud_CoAPExport.h"
|
||||
#include "CoAPSerialize.h"
|
||||
#include "CoAPDeserialize.h"
|
||||
#include "Cloud_CoAPPlatform.h"
|
||||
|
||||
|
||||
#define COAPAckMsg(header) \
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) \
|
||||
&&(header.type == COAP_MESSAGE_TYPE_ACK))
|
||||
|
||||
#define Cloud_CoAPRespMsg(header)\
|
||||
((header.code >= 0x40) && (header.code < 0xc0))
|
||||
|
||||
#define Cloud_CoAPPingMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE)\
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define Cloud_CoAPRstMsg(header)\
|
||||
(header.type == COAP_MESSAGE_TYPE_RST)
|
||||
|
||||
#define Cloud_CoAPCONRespMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_205_CONTENT) \
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define Cloud_CoAPReqMsg(header)\
|
||||
((1 <= header.code) && (32 > header.code))
|
||||
|
||||
|
||||
#define COAP_CUR_VERSION 1
|
||||
#define COAP_WAIT_TIME_MS 2000
|
||||
#define COAP_MAX_MESSAGE_ID 65535
|
||||
#define COAP_MAX_RETRY_COUNT 4
|
||||
#define COAP_ACK_TIMEOUT 2
|
||||
#define COAP_ACK_RANDOM_FACTOR 1
|
||||
#define COAP_MAX_TRANSMISSION_SPAN 10
|
||||
|
||||
unsigned short Cloud_CoAPMessageId_gen(Cloud_CoAPContext *context)
|
||||
{
|
||||
unsigned short msg_id = 0;
|
||||
msg_id = ((COAP_MAX_MESSAGE_ID == context->message_id) ? 1 : context->message_id++);
|
||||
return msg_id;
|
||||
}
|
||||
|
||||
int Cloud_CoAPMessageHandler_set(Cloud_CoAPMessage *message, Cloud_CoAPRespMsgHandler resp)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->resp = resp;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int Cloud_CoAPMessageList_add(Cloud_CoAPContext *context, Cloud_CoAPMessage *message, int len)
|
||||
{
|
||||
Cloud_CoAPSendNode *node = NULL;
|
||||
node = coap_malloc(sizeof(Cloud_CoAPSendNode));
|
||||
|
||||
if (NULL != node) {
|
||||
node->acked = 0;
|
||||
node->user = message->user;
|
||||
node->msgid = message->header.msgid;
|
||||
node->resp = message->resp;
|
||||
node->msglen = len;
|
||||
node->timeout_val = COAP_ACK_TIMEOUT * COAP_ACK_RANDOM_FACTOR;
|
||||
|
||||
if (COAP_MESSAGE_TYPE_CON == message->header.type) {
|
||||
node->timeout = node->timeout_val;
|
||||
node->retrans_count = 0;
|
||||
} else {
|
||||
node->timeout = COAP_MAX_TRANSMISSION_SPAN;
|
||||
node->retrans_count = COAP_MAX_RETRY_COUNT;
|
||||
}
|
||||
node->tokenlen = message->header.tokenlen;
|
||||
memcpy(node->token, message->token, message->header.tokenlen);
|
||||
node->message = (unsigned char *)coap_malloc(len);
|
||||
if (NULL != node->message) {
|
||||
memcpy(node->message, context->sendbuf, len);
|
||||
}
|
||||
|
||||
if (&context->list.count >= &context->list.maxcount) {
|
||||
coap_free(node);
|
||||
return -1;
|
||||
} else {
|
||||
list_add_tail(&node->sendlist, &context->list.sendlist);
|
||||
context->list.count ++;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int Cloud_CoAPMessage_send(Cloud_CoAPContext *context, Cloud_CoAPMessage *message)
|
||||
{
|
||||
unsigned int ret = COAP_SUCCESS;
|
||||
unsigned short msglen = 0;
|
||||
|
||||
if (NULL == message || NULL == context) {
|
||||
return (COAP_ERROR_INVALID_PARAM);
|
||||
}
|
||||
|
||||
/* TODO: get the message length */
|
||||
/* msglen = CoAPSerialize_MessageLength(message); */
|
||||
msglen = CoAPSerialize_MessageLength(message);
|
||||
if (COAP_MSG_MAX_PDU_LEN < msglen) {
|
||||
COAP_INFO("The message length %d is too loog", msglen);
|
||||
return COAP_ERROR_DATA_SIZE;
|
||||
}
|
||||
|
||||
memset(context->sendbuf, 0x00, COAP_MSG_MAX_PDU_LEN);
|
||||
msglen = CoAPSerialize_Message(message, context->sendbuf, COAP_MSG_MAX_PDU_LEN);
|
||||
COAP_DEBUG("----The message length %d-----", msglen);
|
||||
|
||||
|
||||
ret = Cloud_CoAPNetwork_write(&context->network, context->sendbuf, (unsigned int)msglen);
|
||||
if (COAP_SUCCESS == ret) {
|
||||
if (Cloud_CoAPReqMsg(message->header) || Cloud_CoAPCONRespMsg(message->header)) {
|
||||
COAP_DEBUG("Add message id %d len %d to the list",
|
||||
message->header.msgid, msglen);
|
||||
Cloud_CoAPMessageList_add(context, message, msglen);
|
||||
} else {
|
||||
COAP_DEBUG("The message doesn't need to be retransmitted");
|
||||
}
|
||||
} else {
|
||||
COAP_ERR("CoAP transport write failed, return %d", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int Cloud_CoAPAckMessage_handle(Cloud_CoAPContext *context, Cloud_CoAPMessage *message)
|
||||
{
|
||||
Cloud_CoAPSendNode *node = NULL;
|
||||
|
||||
list_for_each_entry(node, &context->list.sendlist, sendlist, Cloud_CoAPSendNode) {
|
||||
if (node->msgid == message->header.msgid) {
|
||||
node->acked = 1;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int Cloud_CoAPAckMessage_send(Cloud_CoAPContext *context, unsigned short msgid)
|
||||
{
|
||||
Cloud_CoAPMessage message;
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageId_set(&message, msgid);
|
||||
return Cloud_CoAPMessage_send(context, &message);
|
||||
}
|
||||
|
||||
static int Cloud_CoAPRespMessage_handle(Cloud_CoAPContext *context, Cloud_CoAPMessage *message)
|
||||
{
|
||||
Cloud_CoAPSendNode *node = NULL;
|
||||
|
||||
if (COAP_MESSAGE_TYPE_CON == message->header.type) {
|
||||
Cloud_CoAPAckMessage_send(context, message->header.msgid);
|
||||
}
|
||||
|
||||
|
||||
list_for_each_entry(node, &context->list.sendlist, sendlist, Cloud_CoAPSendNode) {
|
||||
if (0 != node->tokenlen && node->tokenlen == message->header.tokenlen
|
||||
&& 0 == memcmp(node->token, message->token, message->header.tokenlen)) {
|
||||
|
||||
#ifdef INFRA_LOG_NETWORK_PAYLOAD
|
||||
COAP_DEBUG("Find the node by token");
|
||||
COAP_INFO("Downstream Payload:");
|
||||
iotx_facility_json_print((const char *)message->payload, LOG_INFO_LEVEL, '<');
|
||||
#endif
|
||||
message->user = node->user;
|
||||
if (COAP_MSG_CODE_400_BAD_REQUEST <= message->header.code) {
|
||||
/* TODO:i */
|
||||
if (NULL != context->notifier) {
|
||||
/* context->notifier(message->header.code, message); */
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != node->resp) {
|
||||
node->resp(node->user, message);
|
||||
}
|
||||
COAP_DEBUG("Remove the message id %d from list", node->msgid);
|
||||
list_del_init(&node->sendlist);
|
||||
context->list.count--;
|
||||
if (NULL != node->message) {
|
||||
coap_free(node->message);
|
||||
}
|
||||
coap_free(node);
|
||||
node = NULL;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
static void Cloud_CoAPMessage_handle(Cloud_CoAPContext *context,
|
||||
unsigned char *buf,
|
||||
unsigned short datalen)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
Cloud_CoAPMessage message;
|
||||
unsigned char code, msgclass, detail;
|
||||
memset(&message, 0x00, sizeof(Cloud_CoAPMessage));
|
||||
|
||||
ret = CoAPDeserialize_Message(&message, buf, datalen);
|
||||
code = (unsigned char)message.header.code;
|
||||
msgclass = code >> 5;
|
||||
detail = code & 0x1F;
|
||||
|
||||
COAP_DEBUG("Version : %d", message.header.version);
|
||||
COAP_DEBUG("Code : %d.%02d(0x%x)", msgclass, detail, code);
|
||||
COAP_DEBUG("Type : 0x%x", message.header.type);
|
||||
COAP_DEBUG("Msgid : %d", message.header.msgid);
|
||||
COAP_DEBUG("Option : %d", message.optcount);
|
||||
COAP_DEBUG("Payload Len : %d", message.payloadlen);
|
||||
|
||||
msgclass = msgclass;
|
||||
detail = detail;
|
||||
|
||||
if (COAP_SUCCESS != ret) {
|
||||
if (NULL != context->notifier) {
|
||||
/* TODO: */
|
||||
/* context->notifier(context, event); */
|
||||
}
|
||||
}
|
||||
|
||||
if (COAPAckMsg(message.header)) {
|
||||
COAP_DEBUG("Receive CoAP ACK Message,ID %d", message.header.msgid);
|
||||
Cloud_CoAPAckMessage_handle(context, &message);
|
||||
|
||||
} else if (Cloud_CoAPRespMsg(message.header)) {
|
||||
COAP_DEBUG("Receive CoAP Response Message,ID %d", message.header.msgid);
|
||||
Cloud_CoAPRespMessage_handle(context, &message);
|
||||
}
|
||||
}
|
||||
|
||||
int Cloud_CoAPMessage_recv(Cloud_CoAPContext *context, unsigned int timeout, int readcount)
|
||||
{
|
||||
int len = 0;
|
||||
int count = readcount;
|
||||
|
||||
while (1) {
|
||||
len = Cloud_CoAPNetwork_read(&context->network, context->recvbuf,
|
||||
COAP_MSG_MAX_PDU_LEN, timeout);
|
||||
if (len > 0) {
|
||||
if (0 == readcount) {
|
||||
Cloud_CoAPMessage_handle(context, context->recvbuf, len);
|
||||
} else {
|
||||
count--;
|
||||
Cloud_CoAPMessage_handle(context, context->recvbuf, len);
|
||||
if (0 == count) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Cloud_CoAPMessage_cycle(Cloud_CoAPContext *context)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
Cloud_CoAPSendNode *node = NULL, *next = NULL;
|
||||
Cloud_CoAPMessage_recv(context, context->waittime, 0);
|
||||
|
||||
list_for_each_entry_safe(node, next, &context->list.sendlist, sendlist, Cloud_CoAPSendNode) {
|
||||
if (NULL != node) {
|
||||
if (node->timeout == 0) {
|
||||
if (node->retrans_count < COAP_MAX_RETRY_COUNT && (0 == node->acked)) {
|
||||
node->timeout = node->timeout_val * 2;
|
||||
node->timeout_val = node->timeout;
|
||||
node->retrans_count++;
|
||||
COAP_DEBUG("Retansmit the message id %d len %d", node->msgid, node->msglen);
|
||||
ret = Cloud_CoAPNetwork_write(&context->network, node->message, node->msglen);
|
||||
if (ret != COAP_SUCCESS) {
|
||||
if (NULL != context->notifier) {
|
||||
/* TODO: */
|
||||
/* context->notifier(context, event); */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((node->timeout > COAP_MAX_TRANSMISSION_SPAN) ||
|
||||
(node->retrans_count >= COAP_MAX_RETRY_COUNT)) {
|
||||
if (NULL != context->notifier) {
|
||||
/* TODO: */
|
||||
/* context->notifier(context, event); */
|
||||
}
|
||||
|
||||
/*Remove the node from the list*/
|
||||
list_del_init(&node->sendlist);
|
||||
context->list.count--;
|
||||
COAP_INFO("Retransmit timeout,remove the message id %d count %d",
|
||||
node->msgid, context->list.count);
|
||||
coap_free(node->message);
|
||||
coap_free(node);
|
||||
}
|
||||
} else {
|
||||
node->timeout--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "CoAPSerialize.h"
|
||||
#include "CoAPDeserialize.h"
|
||||
#if 0
|
||||
#include "CoAPResource.h"
|
||||
#include "CoAPObserve.h"
|
||||
#include "CoAPInternal.h"
|
||||
#endif
|
||||
#include "CoAPPlatform.h"
|
||||
|
||||
#define COAPAckMsg(header) \
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) \
|
||||
&&(header.type == COAP_MESSAGE_TYPE_ACK))
|
||||
|
||||
#define CoAPRespMsg(header)\
|
||||
((header.code >= 0x40) && (header.code < 0xc0))
|
||||
|
||||
#define CoAPPingMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE)\
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define CoAPResetMsg(header)\
|
||||
(header.type == COAP_MESSAGE_TYPE_RST)
|
||||
|
||||
#define CoAPCONRespMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_205_CONTENT) \
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define CoAPReqMsg(header)\
|
||||
((1 <= header.code) && (32 > header.code))
|
||||
|
||||
|
||||
#define COAP_CUR_VERSION 1
|
||||
#define COAP_WAIT_TIME_MS 2000
|
||||
#define COAP_MAX_MESSAGE_ID 65535
|
||||
#define COAP_MAX_RETRY_COUNT 4
|
||||
#define COAP_ACK_TIMEOUT 2
|
||||
#define COAP_ACK_RANDOM_FACTOR 1
|
||||
#define COAP_MAX_TRANSMISSION_SPAN 10
|
||||
|
||||
int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum, unsigned char *data, unsigned short datalen)
|
||||
{
|
||||
unsigned char *ptr = NULL;
|
||||
if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
message->options[message->optcount].num = optnum - message->optdelta;
|
||||
message->options[message->optcount].len = datalen;
|
||||
ptr = (unsigned char *)coap_malloc(datalen);
|
||||
if (NULL == ptr) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
memset(ptr, 0x00, datalen);
|
||||
memcpy(ptr, data, datalen);
|
||||
message->options[message->optcount].val = ptr;
|
||||
message->optdelta = optnum;
|
||||
message->optcount ++;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum, unsigned char *data, unsigned short *datalen)
|
||||
{
|
||||
unsigned char index = 0;
|
||||
|
||||
for (index = 0; index < message->optcount; index++) {
|
||||
if (message->options[index].num == optnum) {
|
||||
if (*datalen >= message->options[index].len) {
|
||||
memcpy(data, message->options[index].val, message->options[index].len);
|
||||
*datalen = message->options[index].len;
|
||||
return COAP_SUCCESS;
|
||||
} else {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum, unsigned int data)
|
||||
{
|
||||
unsigned char *ptr = NULL;
|
||||
if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
message->options[message->optcount].num = optnum - message->optdelta;
|
||||
|
||||
if (0 == data) {
|
||||
message->options[message->optcount].len = 0;
|
||||
} else if (255 >= data) {
|
||||
message->options[message->optcount].len = 1;
|
||||
ptr = (unsigned char *)coap_malloc(1);
|
||||
if (NULL != ptr) {
|
||||
*ptr = (unsigned char)data;
|
||||
}
|
||||
} else if (65535 >= data) {
|
||||
message->options[message->optcount].len = 2;
|
||||
ptr = (unsigned char *)coap_malloc(2);
|
||||
if (NULL != ptr) {
|
||||
*ptr = (unsigned char)((data & 0xFF00) >> 8);
|
||||
*(ptr + 1) = (unsigned char)(data & 0x00FF);
|
||||
}
|
||||
} else {
|
||||
message->options[message->optcount].len = 4;
|
||||
ptr = (unsigned char *)coap_malloc(4);
|
||||
if (NULL != ptr) {
|
||||
*ptr = (unsigned char)((data & 0xFF000000) >> 24);
|
||||
*(ptr + 1) = (unsigned char)((data & 0x00FF0000) >> 16);
|
||||
*(ptr + 2) = (unsigned char)((data & 0x0000FF00) >> 8);
|
||||
*(ptr + 3) = (unsigned char)(data & 0x000000FF);
|
||||
}
|
||||
}
|
||||
message->options[message->optcount].val = ptr;
|
||||
message->optdelta = optnum;
|
||||
message->optcount += 1;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPUintOption_get(CoAPMessage *message,
|
||||
unsigned short optnum,
|
||||
unsigned int *data)
|
||||
{
|
||||
|
||||
unsigned char index = 0;
|
||||
|
||||
for (index = 0; index < message->optcount; index++) {
|
||||
if (message->options[index].num == optnum) {
|
||||
int byte = 0;
|
||||
switch (message->options[index].len) {
|
||||
case 1:
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
case 2:
|
||||
*data |= (message->options[index].val[byte++] << 8);
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
case 3:
|
||||
*data |= (message->options[index].val[byte++] << 16);
|
||||
*data |= (message->options[index].val[byte++] << 8);
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
case 4:
|
||||
*data |= (message->options[index].val[byte++] << 24);
|
||||
*data |= (message->options[index].val[byte++] << 16);
|
||||
*data |= (message->options[index].val[byte++] << 8);
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
default:
|
||||
*data = 0;
|
||||
break;
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
int CoAPOption_present(CoAPMessage *message, unsigned short option)
|
||||
{
|
||||
unsigned char index = 0;
|
||||
|
||||
|
||||
for (index = 0; index < message->optcount; index++) {
|
||||
if (message->options[index].num == option) {
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->header.msgid = msgid;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageType_set(CoAPMessage *message, unsigned char type)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
if (COAP_MESSAGE_TYPE_CON != type && COAP_MESSAGE_TYPE_NON != type
|
||||
&& COAP_MESSAGE_TYPE_ACK != type && COAP_MESSAGE_TYPE_RST != type) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
message->header.type = type;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->header.code = code;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageCode_get(CoAPMessage *message, CoAPMessageCode *code)
|
||||
{
|
||||
if (NULL == message || NULL == code) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
*code = message->header.code;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
|
||||
unsigned char tokenlen)
|
||||
{
|
||||
if (NULL == message || NULL == token) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
if (COAP_MSG_MAX_TOKEN_LEN < tokenlen) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
memcpy(message->token, token, tokenlen);
|
||||
message->header.tokenlen = tokenlen;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageUserData_set(CoAPMessage *message, void *userdata)
|
||||
{
|
||||
if (NULL == message || NULL == userdata) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->user = userdata;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageKeep_Set(CoAPMessage *message, int keep)
|
||||
{
|
||||
if (NULL == message || keep < 0) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->keep = keep;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
|
||||
unsigned short payloadlen)
|
||||
{
|
||||
if (NULL == message || (0 < payloadlen && NULL == payload)) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->payload = payload;
|
||||
message->payloadlen = payloadlen;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessage_init(CoAPMessage *message)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
memset(message, 0x00, sizeof(CoAPMessage));
|
||||
message->header.version = COAP_CUR_VERSION;
|
||||
message->header.type = COAP_MESSAGE_TYPE_ACK;
|
||||
message->header.tokenlen = 0;
|
||||
message->header.code = COAP_MSG_CODE_EMPTY_MESSAGE;
|
||||
message->header.msgid = 0;
|
||||
message->payload = NULL;
|
||||
message->payloadlen = 0;
|
||||
message->optcount = 0;
|
||||
message->optdelta = 0;
|
||||
message->handler = NULL;
|
||||
message->keep = 0;
|
||||
for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
|
||||
message->options[count].len = 0;
|
||||
message->options[count].num = 0;
|
||||
message->options[count].val = NULL;
|
||||
}
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessage_destory(CoAPMessage *message)
|
||||
{
|
||||
int count = 0;
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
|
||||
if (NULL != message->options[count].val) {
|
||||
coap_free(message->options[count].val);
|
||||
message->options[count].val = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "Cloud_CoAPExport.h"
|
||||
#include "Cloud_CoAPNetwork.h"
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
static void *Cloud_CoAPDTLS_Malloc(uint32_t size)
|
||||
{
|
||||
#ifdef INFRA_MEM_STATS
|
||||
return LITE_malloc(size, MEM_MAGIC, "dtls");
|
||||
#else
|
||||
return HAL_Malloc(size);
|
||||
#endif
|
||||
}
|
||||
static void Cloud_CoAPDTLS_Free(void *ptr)
|
||||
{
|
||||
#ifdef INFRA_MEM_STATS
|
||||
LITE_free(ptr);
|
||||
#else
|
||||
HAL_Free((void *)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Cloud_CoAPNetworkDTLS_freeSession(void *p_session);
|
||||
|
||||
unsigned int Cloud_CoAPNetworkDTLS_read(void *p_session,
|
||||
unsigned char *p_data,
|
||||
unsigned int *p_datalen,
|
||||
unsigned int timeout)
|
||||
{
|
||||
unsigned int err_code = DTLS_SUCCESS;
|
||||
const unsigned int read_len = *p_datalen;
|
||||
DTLSContext *context = NULL;
|
||||
|
||||
COAP_TRC("<< secure_datagram_read, read buffer len %d, timeout %d", read_len, timeout);
|
||||
(void)read_len;
|
||||
if (NULL != p_session) {
|
||||
/* read dtls application data*/
|
||||
context = (DTLSContext *)p_session;
|
||||
err_code = HAL_DTLSSession_read(context, p_data, p_datalen, timeout);
|
||||
if (DTLS_PEER_CLOSE_NOTIFY == err_code
|
||||
|| DTLS_FATAL_ALERT_MESSAGE == err_code) {
|
||||
COAP_INFO("dtls session read failed, return (0x%04x)", err_code);
|
||||
Cloud_CoAPNetworkDTLS_freeSession(context);
|
||||
}
|
||||
if (DTLS_SUCCESS == err_code) {
|
||||
return COAP_SUCCESS;
|
||||
} else {
|
||||
return COAP_ERROR_READ_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
unsigned int Cloud_CoAPNetworkDTLS_write(void *p_session,
|
||||
const unsigned char *p_data,
|
||||
unsigned int *p_datalen)
|
||||
{
|
||||
unsigned int err_code = DTLS_SUCCESS;
|
||||
if (NULL != p_session) {
|
||||
err_code = HAL_DTLSSession_write((DTLSContext *)p_session, p_data, p_datalen);
|
||||
if (DTLS_SUCCESS == err_code) {
|
||||
return COAP_SUCCESS;
|
||||
} else {
|
||||
return COAP_ERROR_WRITE_FAILED;
|
||||
}
|
||||
}
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
static void Cloud_CoAPNetworkDTLS_freeSession(void *p_session)
|
||||
{
|
||||
/* Free the session.*/
|
||||
HAL_DTLSSession_free((DTLSContext *)p_session);
|
||||
}
|
||||
|
||||
void *Cloud_CoAPNetworkDTLS_createSession(char *p_host,
|
||||
unsigned short port,
|
||||
unsigned char *p_ca_cert_pem)
|
||||
{
|
||||
DTLSContext *context = NULL;
|
||||
dtls_hooks_t dtls_hooks;
|
||||
coap_dtls_options_t dtls_options;
|
||||
|
||||
memset(&dtls_hooks, 0, sizeof(dtls_hooks_t));
|
||||
dtls_hooks.malloc = Cloud_CoAPDTLS_Malloc;
|
||||
dtls_hooks.free = Cloud_CoAPDTLS_Free;
|
||||
|
||||
HAL_DTLSHooks_set(&dtls_hooks);
|
||||
|
||||
memset(&dtls_options, 0x00, sizeof(coap_dtls_options_t));
|
||||
dtls_options.p_ca_cert_pem = p_ca_cert_pem;
|
||||
dtls_options.p_host = p_host;
|
||||
dtls_options.port = port;
|
||||
|
||||
context = HAL_DTLSSession_create(&dtls_options);
|
||||
return (void *)context;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned int Cloud_CoAPNetwork_write(coap_network_t *p_network,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen)
|
||||
{
|
||||
int rc = COAP_ERROR_WRITE_FAILED;
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_ENDPOINT_DTLS == p_network->ep_type) {
|
||||
rc = Cloud_CoAPNetworkDTLS_write(p_network->context, p_data, &datalen);
|
||||
} else {
|
||||
#endif
|
||||
rc = HAL_UDP_write((intptr_t)p_network->context, p_data, datalen);
|
||||
COAP_DEBUG("[CoAP-NWK]: Network write return %d", rc);
|
||||
|
||||
if (-1 == rc) {
|
||||
rc = COAP_ERROR_WRITE_FAILED;
|
||||
} else {
|
||||
rc = COAP_SUCCESS;
|
||||
}
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
return (unsigned int)rc;
|
||||
}
|
||||
|
||||
int Cloud_CoAPNetwork_read(coap_network_t *network, unsigned char *data,
|
||||
unsigned int datalen, unsigned int timeout)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_ENDPOINT_DTLS == network->ep_type) {
|
||||
len = datalen;
|
||||
memset(data, 0x00, datalen);
|
||||
Cloud_CoAPNetworkDTLS_read(network->context, data, (unsigned int *)&len, timeout);
|
||||
} else {
|
||||
#endif
|
||||
memset(data, 0x00, datalen);
|
||||
len = HAL_UDP_readTimeout((intptr_t)network->context,
|
||||
data, COAP_MSG_MAX_PDU_LEN, timeout);
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
if (len > 0) {
|
||||
COAP_TRC("<< CoAP recv %d bytes data", len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int Cloud_CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t *p_network)
|
||||
{
|
||||
unsigned int err_code = COAP_SUCCESS;
|
||||
|
||||
if (NULL == p_param || NULL == p_network) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* TODO : Parse the url here */
|
||||
p_network->ep_type = p_param->ep_type;
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_ENDPOINT_DTLS == p_param->ep_type) {
|
||||
p_network->context = Cloud_CoAPNetworkDTLS_createSession(p_param->p_host,
|
||||
p_param->port, p_param->p_ca_cert_pem);
|
||||
if (NULL == p_network->context) {
|
||||
return COAP_ERROR_NET_INIT_FAILED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (COAP_ENDPOINT_NOSEC == p_param->ep_type
|
||||
|| COAP_ENDPOINT_PSK == p_param->ep_type) {
|
||||
/*Create udp socket*/
|
||||
p_network->context = (void *)HAL_UDP_create(p_param->p_host, p_param->port);
|
||||
if ((void *) - 1 == p_network->context) {
|
||||
return COAP_ERROR_NET_INIT_FAILED;
|
||||
}
|
||||
}
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
unsigned int Cloud_CoAPNetwork_deinit(coap_network_t *p_network)
|
||||
{
|
||||
unsigned int err_code = COAP_SUCCESS;
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_ENDPOINT_DTLS == p_network->ep_type) {
|
||||
Cloud_CoAPNetworkDTLS_freeSession(p_network->context);
|
||||
p_network->context = NULL;
|
||||
}
|
||||
#endif
|
||||
if (COAP_ENDPOINT_NOSEC == p_network->ep_type
|
||||
|| COAP_ENDPOINT_PSK == p_network->ep_type) {
|
||||
HAL_UDP_close_without_connect((intptr_t)p_network->context);
|
||||
}
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __COAP_PLATFORM_OS_H__
|
||||
#define __COAP_PLATFORM_OS_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define coap_malloc(size) LITE_malloc(size, MEM_MAGIC, "coap.local")
|
||||
#define coap_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define coap_malloc(size) HAL_Malloc(size)
|
||||
#define coap_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#ifdef INFRA_LOG
|
||||
#include "infra_log.h"
|
||||
#define COAP_ERR(...) log_err("coap_local", __VA_ARGS__)
|
||||
#define COAP_WRN(...) log_warning("coap_local", __VA_ARGS__)
|
||||
#define COAP_INFO(...) log_info("coap_local", __VA_ARGS__)
|
||||
#define COAP_TRC(...) log_debug("coap_local", __VA_ARGS__)
|
||||
#define COAP_DUMP(...) log_debug("coap_local", __VA_ARGS__)
|
||||
#define COAP_DEBUG(...) log_debug("coap_local", __VA_ARGS__)
|
||||
#define COAP_FLOW(...) log_flow("coap_local", __VA_ARGS__)
|
||||
#else
|
||||
#define COAP_ERR(...)
|
||||
#define COAP_WRN(...)
|
||||
#define COAP_INFO(...)
|
||||
#define COAP_TRC(...)
|
||||
#define COAP_DUMP(...)
|
||||
#define COAP_DEBUG(...)
|
||||
#define COAP_FLOW(...)
|
||||
#endif
|
||||
|
||||
int platform_is_multicast(const char *ip_str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __COAP_SERIALIZE_H__
|
||||
#define __COAP_SERIALIZE_H__
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg);
|
||||
|
||||
int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "CoAPSerialize.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
int CoAPSerialize_Header(CoAPMessage *msg, unsigned char *buf, unsigned short buflen)
|
||||
{
|
||||
if(4 > buflen){
|
||||
return 0;
|
||||
}
|
||||
buf[0] = (((msg->header.version & 0x3) << 6) | ((msg->header.type & 0x3) << 4))
|
||||
| (msg->header.tokenlen & 0x0F);
|
||||
|
||||
buf[1] = msg->header.code;
|
||||
buf[2] = (msg->header.msgid & 0xFF00) >> 8;
|
||||
buf[3] = (msg->header.msgid & 0x00FF);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int CoAPSerialize_Token(CoAPMessage *msg, unsigned char * buf, unsigned short buflen)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if(buflen < msg->header.tokenlen){
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < msg->header.tokenlen; i++){
|
||||
buf[i] = msg->token[i];
|
||||
}
|
||||
return msg->header.tokenlen;
|
||||
}
|
||||
|
||||
static unsigned short CoAPSerialize_Option(CoAPMsgOption *option, unsigned char *buf)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
if(269 <= option->num){
|
||||
*ptr = ((14 & 0x0F) << 4);
|
||||
}
|
||||
else if(13 <= option->num){
|
||||
*ptr = ((13 & 0x0F) << 4);
|
||||
}
|
||||
else{
|
||||
*ptr = option->num << 4;
|
||||
}
|
||||
|
||||
if (269 <= option->len){
|
||||
*ptr |= (14 & 0x0F);
|
||||
}
|
||||
else if(13 <= option->len){
|
||||
*ptr |= (13 & 0x0F);
|
||||
}
|
||||
else{
|
||||
*ptr |= (option->len & 0x0F);
|
||||
}
|
||||
ptr ++;
|
||||
|
||||
if (269 <= option->num){
|
||||
*ptr = (unsigned char)(((option->num - 269) & 0xFF00) >> 8);
|
||||
*(ptr+1) = (unsigned char)(((option->num - 269) & 0x00FF));
|
||||
ptr += 2;
|
||||
}
|
||||
else if(13 <= option->num){
|
||||
*ptr = (unsigned char)(option->num - 13);
|
||||
ptr ++;
|
||||
}
|
||||
|
||||
|
||||
if (269 <= option->len){
|
||||
*ptr = (unsigned char)(((option->len - 269) & 0xFF00) >> 8);
|
||||
*(ptr+1) = (unsigned char)(((option->len - 269) & 0x00FF));
|
||||
ptr += 2;
|
||||
}
|
||||
else if(13 <= option->len){
|
||||
*ptr = (unsigned char)(option->len - 13);
|
||||
ptr ++;
|
||||
}
|
||||
|
||||
|
||||
memcpy(ptr, option->val, option->len);
|
||||
ptr += option->len;
|
||||
|
||||
return (int)(ptr - buf);
|
||||
}
|
||||
|
||||
unsigned short CoAPSerialize_Options(CoAPMessage *msg, unsigned char * buf, unsigned short buflen)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned short count = 0;
|
||||
|
||||
for (i = 0; i < msg->optcount; i++)
|
||||
{
|
||||
unsigned short len = 0;
|
||||
len = CoAPSerialize_Option(&msg->options[i], &buf[count]);
|
||||
if (0 < len){
|
||||
count += len;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static unsigned short CoAPSerialize_OptionLen(CoAPMsgOption *option)
|
||||
{
|
||||
unsigned short len = 1;
|
||||
|
||||
if(269 <= option->num){
|
||||
len += 2;
|
||||
}
|
||||
else if(13 <= option->num){
|
||||
len += 1;
|
||||
}
|
||||
else{
|
||||
}
|
||||
|
||||
if (269 <= option->len){
|
||||
len += 2;
|
||||
}
|
||||
else if(13 <= option->len){
|
||||
len += 1;
|
||||
}
|
||||
else{
|
||||
}
|
||||
|
||||
len += option->len;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
unsigned short CoAPSerialize_OptionsLen(CoAPMessage *msg)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned short count = 0;
|
||||
|
||||
for (i = 0; i < msg->optcount; i++)
|
||||
{
|
||||
unsigned short len = 0;
|
||||
len = CoAPSerialize_OptionLen(&msg->options[i]);
|
||||
if (0 < len){
|
||||
count += len;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int CoAPSerialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
if(msg->payloadlen + 1 > buflen){
|
||||
return 0;
|
||||
}
|
||||
if(msg->payloadlen > 0 && NULL != msg->payload)
|
||||
{
|
||||
*buf = 0xFF;
|
||||
buf ++;
|
||||
memcpy(buf, msg->payload, msg->payloadlen);
|
||||
return msg->payloadlen + 1;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg)
|
||||
{
|
||||
unsigned short msglen = 4;
|
||||
|
||||
msglen += msg->header.tokenlen;
|
||||
msglen += CoAPSerialize_OptionsLen(msg);
|
||||
|
||||
if(0 < msg->payloadlen){
|
||||
msglen += msg->payloadlen;
|
||||
msglen += 1; /*CoAP payload marker*/
|
||||
}
|
||||
|
||||
return msglen;
|
||||
}
|
||||
|
||||
int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short count = 0;
|
||||
unsigned short remlen = buflen;
|
||||
|
||||
if(NULL == buf || NULL == msg){
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
count = CoAPSerialize_Header(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPSerialize_Token(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPSerialize_Options(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPSerialize_Payload(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
return (buflen-remlen);
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __IOTX_COAP_API_H__
|
||||
#define __IOTX_COAP_API_H__
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "infra_defs.h"
|
||||
|
||||
/*iotx return code definition*/
|
||||
typedef enum {
|
||||
IOTX_ERR_RECV_MSG_TIMEOUT = -9, /*Receive message timeout */
|
||||
IOTX_ERR_SEND_MSG_FAILED = -8, /* Send message failed*/
|
||||
IOTX_ERR_MSG_TOO_LOOG = -7, /* The payload too loog */
|
||||
IOTX_ERR_URI_TOO_LOOG = -6, /* URI length too long */
|
||||
IOTX_ERR_NOT_AUTHED = -5, /* Client isn't authed */
|
||||
IOTX_ERR_AUTH_FAILED = -4, /* Client authed failed */
|
||||
IOTX_ERR_BUFF_TOO_SHORT = -3, /* Buffer too short */
|
||||
IOTX_ERR_NO_MEM = -2, /* Malloc failed */
|
||||
IOTX_ERR_INVALID_PARAM = -1, /* Invalid parameter */
|
||||
IOTX_SUCCESS = 0, /* Success */
|
||||
} iotx_ret_code_t;
|
||||
|
||||
/* The message payload encode format */
|
||||
typedef enum {
|
||||
IOTX_CONTENT_TYPE_JSON,
|
||||
IOTX_CONTENT_TYPE_CBOR,
|
||||
} iotx_content_type_t;
|
||||
|
||||
/* The message type */
|
||||
typedef enum {
|
||||
IOTX_MESSAGE_CON = 0, /* confirmable message */
|
||||
IOTX_MESSAGE_NON = 1, /* non-confirmable message */
|
||||
IOTX_MESSAGE_ACK = 2, /* acknowledgement message */
|
||||
IOTX_MESSAGE_RST = 3, /* reset message */
|
||||
} iotx_msg_type_t;
|
||||
|
||||
/* IoTx events to notify application */
|
||||
typedef enum {
|
||||
IOTX_COAP_EVENT_SEND_FAILED = 0,
|
||||
IOTX_COAP_EVENT_RECV_FAILED = 1,
|
||||
IOTX_COAP_EVENT_AUTH_FAILED = 2,
|
||||
} iotx_coap_event_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_COAP_RESP_CODE_CONTENT = 0x45, /* Mapping to 2.05, Content*/
|
||||
IOTX_COAP_RESP_CODE_BAD_REQUEST = 0x80, /* Mapping to 4.00, Bad Request*/
|
||||
IOTX_COAP_RESP_CODE_UNAUTHORIZED = 0x81, /* Mapping to 4.01, Token is invalid or expire*/
|
||||
IOTX_COAP_RESP_CODE_NOT_FOUND = 0x84, /* Mapping to 4.04, Path or uri is not found*/
|
||||
IOTX_COAP_RESP_CODE_URL_TOO_LONG = 0x8E, /* Mapping to 4.14, The request url is too long*/
|
||||
IOTX_COAP_RESP_CODE_INTERNAL_SERVER_ERROR = 0xA0,/* Mapping to 5.00, Internal server error*/
|
||||
|
||||
} iotx_coap_resp_code_t;
|
||||
|
||||
/* Callback function to notify the application events.*/
|
||||
typedef void (*iotx_event_handle_t)(void *context, iotx_coap_event_t event, void *p_data);
|
||||
|
||||
/*IoTx device*/
|
||||
typedef struct {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2];
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
|
||||
} iotx_deviceinfo_t;
|
||||
|
||||
typedef struct {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2];
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
|
||||
char module_vendor_id[IOTX_PARTNER_ID_LEN + 1];
|
||||
} iotx_device_info_t;
|
||||
|
||||
/* IoTx initializa parameters */
|
||||
typedef struct {
|
||||
char *p_url; /*Can be NULL*/
|
||||
int wait_time_ms; /*unit is micro second*/
|
||||
iotx_device_info_t *p_devinfo; /*Device info*/
|
||||
iotx_event_handle_t event_handle; /*TODO, not supported now*/
|
||||
} iotx_coap_config_t;
|
||||
|
||||
/* Callback function to handle the response message.*/
|
||||
typedef void (*iotx_response_callback_t)(void *p_arg, void *p_message);
|
||||
|
||||
/* IoTx message definition */
|
||||
typedef struct {
|
||||
unsigned char *p_payload;
|
||||
unsigned short payload_len;
|
||||
iotx_content_type_t content_type;
|
||||
iotx_msg_type_t msg_type;
|
||||
void *user_data;
|
||||
iotx_response_callback_t resp_callback;
|
||||
} iotx_message_t;
|
||||
|
||||
|
||||
/*iotx coap context definition*/
|
||||
typedef void iotx_coap_context_t;
|
||||
|
||||
|
||||
/** @defgroup group_api api
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup group_api_coap coap
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the CoAP client.
|
||||
* This function initialize the data structures and network,
|
||||
* and create the DTLS session.
|
||||
*
|
||||
* @param [in] p_config: Specify the CoAP client parameter.
|
||||
*
|
||||
* @retval NULL : Initialize failed.
|
||||
* @retval NOT_NULL : The contex of CoAP client.
|
||||
* @see None.
|
||||
*/
|
||||
iotx_coap_context_t *IOT_CoAP_Init(iotx_coap_config_t *p_config);
|
||||
|
||||
/**
|
||||
* @brief De-initialize the CoAP client.
|
||||
* This function release CoAP DTLS session.
|
||||
* and release the related resource.
|
||||
*
|
||||
* @param [in] p_context: Pointer of contex, specify the CoAP client.
|
||||
*
|
||||
* @return None.
|
||||
* @see None.
|
||||
*/
|
||||
DLL_IOT_API void IOT_CoAP_Deinit(iotx_coap_context_t **p_context);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle device name authentication with remote server.
|
||||
*
|
||||
* @param [in] p_context: Pointer of contex, specify the CoAP client.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : Authenticate success.
|
||||
* @retval IOTX_ERR_SEND_MSG_FAILED : Send authentication message failed.
|
||||
* @retval IOTX_ERR_AUTH_FAILED : Authenticate failed or timeout.
|
||||
* @see iotx_ret_code_t.
|
||||
*/
|
||||
DLL_IOT_API int IOT_CoAP_DeviceNameAuth(iotx_coap_context_t *p_context);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle CoAP response packet from remote server,
|
||||
* and process timeout request etc..
|
||||
*
|
||||
* @param [in] p_context : Pointer of contex, specify the CoAP client.
|
||||
*
|
||||
* @return status.
|
||||
* @see iotx_ret_code_t.
|
||||
*/
|
||||
DLL_IOT_API int IOT_CoAP_Yield(iotx_coap_context_t *p_context);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a message with specific path to server.
|
||||
* Client must authentication with server before send message.
|
||||
*
|
||||
* @param [in] p_context : Pointer of contex, specify the CoAP client.
|
||||
* @param [in] p_path: Specify the path name.
|
||||
* @param [in] p_message: Message to be sent.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : Send the message success.
|
||||
* @retval IOTX_ERR_MSG_TOO_LOOG : The message length is too long.
|
||||
* @retval IOTX_ERR_NOT_AUTHED : The client hasn't authenticated with server
|
||||
* @see iotx_ret_code_t.
|
||||
*/
|
||||
DLL_IOT_API int IOT_CoAP_SendMessage(iotx_coap_context_t *p_context, char *p_path, iotx_message_t *p_message);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the length and payload pointer of specified message.
|
||||
*
|
||||
* @param [in] p_message: Pointer to the message to get the payload. Should not be NULL.
|
||||
* @param [out] pp_payload: Pointer to the payload.
|
||||
* @param [out] p_len: Size of the payload.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : Get the payload success.
|
||||
* @retval IOTX_ERR_INVALID_PARAM : Can't get the payload due to invalid parameter.
|
||||
* @see iotx_ret_code_t.
|
||||
**/
|
||||
DLL_IOT_API int IOT_CoAP_GetMessagePayload(void *p_message, unsigned char **pp_payload, int *p_len);
|
||||
|
||||
/**
|
||||
* @brief Get the response code from a CoAP message.
|
||||
*
|
||||
* @param [in] p_message: Pointer to the message to add the address information to.
|
||||
* Should not be NULL.
|
||||
* @param [out] p_resp_code: The response code.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : When get the response code to message success.
|
||||
* @retval IOTX_ERR_INVALID_PARAM : Pointer to the message is NULL.
|
||||
* @see iotx_ret_code_t.
|
||||
**/
|
||||
DLL_IOT_API int IOT_CoAP_GetMessageCode(void *p_message, iotx_coap_resp_code_t *p_resp_code);
|
||||
|
||||
/** @} */ /* end of api_coap */
|
||||
/** @} */ /* end of api */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef _COAP_WRAPPER_H_
|
||||
#define _COAP_WRAPPER_H_
|
||||
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_compat.h"
|
||||
#include "wrappers_defs.h"
|
||||
|
||||
void *HAL_Malloc(uint32_t size);
|
||||
void HAL_Free(void *ptr);
|
||||
void HAL_SleepMs(uint32_t ms);
|
||||
uint64_t HAL_UptimeMs(void);
|
||||
void HAL_Srandom(uint32_t seed);
|
||||
uint32_t HAL_Random(uint32_t region);
|
||||
void HAL_Printf(const char *fmt, ...);
|
||||
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
|
||||
|
||||
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
|
||||
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
|
||||
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
|
||||
|
||||
int HAL_SetProductKey(char *product_key);
|
||||
int HAL_SetProductSecret(char *product_secret);
|
||||
int HAL_SetDeviceName(char *device_name);
|
||||
int HAL_SetDeviceSecret(char *device_secret);
|
||||
|
||||
DLL_HAL_API int HAL_DTLSHooks_set(dtls_hooks_t *hooks);
|
||||
DLL_HAL_API DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options);
|
||||
DLL_HAL_API unsigned int HAL_DTLSSession_write(DTLSContext *context,
|
||||
const unsigned char *p_data,
|
||||
unsigned int *p_datalen);
|
||||
DLL_HAL_API unsigned int HAL_DTLSSession_read(DTLSContext *context,
|
||||
unsigned char *p_data,
|
||||
unsigned int *p_datalen,
|
||||
unsigned int timeout_ms);
|
||||
DLL_HAL_API unsigned int HAL_DTLSSession_free(DTLSContext *context);
|
||||
intptr_t HAL_UDP_create(char *host, unsigned short port);
|
||||
intptr_t HAL_UDP_create_without_connect(const char *host, unsigned short port);
|
||||
int HAL_UDP_write(intptr_t p_socket,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen);
|
||||
int HAL_UDP_readTimeout(intptr_t p_socket,
|
||||
unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout);
|
||||
int HAL_UDP_close_without_connect(intptr_t sockfd);
|
||||
int HAL_UDP_recvfrom(intptr_t sockfd,
|
||||
NetworkAddr *p_remote,
|
||||
unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout_ms);
|
||||
int HAL_UDP_sendto(intptr_t sockfd,
|
||||
const NetworkAddr *p_remote,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout_ms);
|
||||
int HAL_UDP_joinmulticast(intptr_t sockfd,
|
||||
char *p_group);
|
||||
uint32_t HAL_Wifi_Get_IP(char ip_str[NETWORK_ADDR_LEN], const char *ifname);
|
||||
p_HAL_Aes128_t HAL_Aes128_Init(
|
||||
const uint8_t *key,
|
||||
const uint8_t *iv,
|
||||
AES_DIR_t dir);
|
||||
int HAL_Aes128_Destroy(p_HAL_Aes128_t aes);
|
||||
int HAL_Aes128_Cbc_Encrypt(
|
||||
p_HAL_Aes128_t aes,
|
||||
const void *src,
|
||||
size_t blockNum,
|
||||
void *dst);
|
||||
int HAL_Aes128_Cbc_Decrypt(
|
||||
p_HAL_Aes128_t aes,
|
||||
const void *src,
|
||||
size_t blockNum,
|
||||
void *dst);
|
||||
void *HAL_MutexCreate(void);
|
||||
void HAL_MutexDestroy(void *mutex);
|
||||
void HAL_MutexLock(void *mutex);
|
||||
void HAL_MutexUnlock(void *mutex);
|
||||
void *HAL_SemaphoreCreate(void);
|
||||
void HAL_SemaphoreDestroy(void *sem);
|
||||
int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
|
||||
void HAL_SemaphorePost(void *sem);
|
||||
int HAL_ThreadCreate(
|
||||
void **thread_handle,
|
||||
void *(*work_routine)(void *),
|
||||
void *arg,
|
||||
hal_os_thread_param_t *hal_os_thread_param,
|
||||
int *stack_used);
|
||||
void HAL_ThreadDelete(void *thread_handle);
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "CoAPServer.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
@@ -0,0 +1,950 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "coap_api.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "Cloud_CoAPPlatform.h"
|
||||
#include "Cloud_CoAPPlatform.h"
|
||||
#include "Cloud_CoAPMessage.h"
|
||||
#include "Cloud_CoAPExport.h"
|
||||
|
||||
#define IOTX_SIGN_LENGTH (40+1)
|
||||
#define IOTX_SIGN_SOURCE_LEN (256)
|
||||
#define IOTX_AUTH_TOKEN_LEN (192+1)
|
||||
#define IOTX_COAP_INIT_TOKEN (0x01020304)
|
||||
#define IOTX_LIST_MAX_ITEM (10)
|
||||
|
||||
#ifndef INFRA_LOG
|
||||
#undef HEXDUMP_DEBUG
|
||||
#undef HEXDUMP_INFO
|
||||
|
||||
#define HEXDUMP_DEBUG(...)
|
||||
#define HEXDUMP_INFO(...)
|
||||
#endif
|
||||
|
||||
#define IOTX_AUTH_STR "auth"
|
||||
#define IOTX_SIGN_SRC_STR "clientId%sdeviceName%sproductKey%s"
|
||||
#define IOTX_SIGN_SRC_STR_WITH_SEQ "clientId%sdeviceName%sproductKey%sseq%d"
|
||||
|
||||
#define IOTX_AUTH_DEVICENAME_STR "{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\",\"sign\":\"%s\"}"
|
||||
#define IOTX_AUTH_DEVICENAME_STR_WITH_SEQ "{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\",\"sign\":\"%s\",\"seq\":\"%d\"}"
|
||||
|
||||
#define IOTX_COAP_ONLINE_DTLS_SERVER_URL "coaps://%s.coap.cn-shanghai.link.aliyuncs.com:5684"
|
||||
#define IOTX_COAP_ONLINE_PSK_SERVER_URL "coap-psk://%s.coap.cn-shanghai.link.aliyuncs.com:5682"
|
||||
|
||||
iotx_coap_context_t *g_coap_context = NULL;
|
||||
|
||||
typedef struct {
|
||||
char *p_auth_token;
|
||||
int auth_token_len;
|
||||
char is_authed;
|
||||
iotx_deviceinfo_t *p_devinfo;
|
||||
Cloud_CoAPContext *p_coap_ctx;
|
||||
unsigned int coap_token;
|
||||
unsigned int seq;
|
||||
unsigned char key[32];
|
||||
iotx_event_handle_t event_handle;
|
||||
} iotx_coap_t;
|
||||
|
||||
|
||||
int iotx_calc_sign(const char *p_device_secret, const char *p_client_id,
|
||||
const char *p_device_name, const char *p_product_key, char sign[IOTX_SIGN_LENGTH])
|
||||
{
|
||||
char *p_msg = NULL;
|
||||
|
||||
p_msg = (char *)coap_malloc(IOTX_SIGN_SOURCE_LEN);
|
||||
if (NULL == p_msg) {
|
||||
return IOTX_ERR_NO_MEM;
|
||||
}
|
||||
memset(sign, 0x00, IOTX_SIGN_LENGTH);
|
||||
memset(p_msg, 0x00, IOTX_SIGN_SOURCE_LEN);
|
||||
|
||||
HAL_Snprintf(p_msg, IOTX_SIGN_SOURCE_LEN,
|
||||
IOTX_SIGN_SRC_STR,
|
||||
p_client_id,
|
||||
p_device_name,
|
||||
p_product_key);
|
||||
utils_hmac_md5(p_msg, strlen(p_msg), sign, p_device_secret, strlen(p_device_secret));
|
||||
|
||||
coap_free(p_msg);
|
||||
COAP_DEBUG("The device name sign: %s", sign);
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
int iotx_calc_sign_with_seq(const char *p_device_secret, const char *p_client_id,
|
||||
const char *p_device_name, const char *p_product_key, unsigned int seq, char sign[IOTX_SIGN_LENGTH])
|
||||
{
|
||||
char *p_msg = NULL;
|
||||
|
||||
p_msg = (char *)coap_malloc(IOTX_SIGN_SOURCE_LEN);
|
||||
if (NULL == p_msg) {
|
||||
return IOTX_ERR_NO_MEM;
|
||||
}
|
||||
memset(sign, 0x00, IOTX_SIGN_LENGTH);
|
||||
memset(p_msg, 0x00, IOTX_SIGN_SOURCE_LEN);
|
||||
|
||||
HAL_Snprintf(p_msg, IOTX_SIGN_SOURCE_LEN,
|
||||
IOTX_SIGN_SRC_STR_WITH_SEQ,
|
||||
p_client_id,
|
||||
p_device_name,
|
||||
p_product_key, seq);
|
||||
COAP_DEBUG("The source string: %s", p_msg);
|
||||
utils_hmac_md5(p_msg, strlen(p_msg), sign, p_device_secret, strlen(p_device_secret));
|
||||
|
||||
coap_free(p_msg);
|
||||
COAP_DEBUG("The device name sign with seq: %s", sign);
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int iotx_get_token_from_json(char *p_str, char *p_token, int len)
|
||||
{
|
||||
char *p_value = NULL;
|
||||
if (NULL == p_str || NULL == p_token) {
|
||||
COAP_ERR("Invalid paramter p_str %p, p_token %p", p_str, p_token);
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
p_value = LITE_json_value_of("token", p_str, 0x1234, "coap.cloud");
|
||||
if (NULL != p_value) {
|
||||
if (len - 1 < strlen(p_value)) {
|
||||
return IOTX_ERR_BUFF_TOO_SHORT;
|
||||
}
|
||||
memset(p_token, 0x00, len);
|
||||
strncpy(p_token, p_value, strlen(p_value));
|
||||
#ifdef INFRA_MEM_STATS
|
||||
LITE_free(p_value);
|
||||
#else
|
||||
HAL_Free((void *)p_value);
|
||||
#endif
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
return IOTX_ERR_AUTH_FAILED;
|
||||
}
|
||||
|
||||
static int iotx_parse_auth_from_json(char *p_str, iotx_coap_t *p_iotx_coap)
|
||||
{
|
||||
int ret = -1;
|
||||
lite_cjson_t root;
|
||||
lite_cjson_t node;
|
||||
unsigned char key[32] = {0};
|
||||
unsigned char buff[128] = {0};
|
||||
unsigned char random[32] = {0};
|
||||
|
||||
if (NULL == p_str || NULL == p_iotx_coap) {
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
memset(&root, 0x00, sizeof(lite_cjson_t));
|
||||
memset(&node, 0x00, sizeof(lite_cjson_t));
|
||||
ret = lite_cjson_parse(p_str, strlen(p_str), &root);
|
||||
if (-1 == ret) {
|
||||
return IOTX_ERR_AUTH_FAILED;
|
||||
}
|
||||
|
||||
ret = lite_cjson_object_item(&root, "token", strlen("token"), &node);
|
||||
if (-1 == ret) {
|
||||
return IOTX_ERR_AUTH_FAILED;
|
||||
}
|
||||
if (p_iotx_coap->auth_token_len - 1 < node.value_length) {
|
||||
return IOTX_ERR_BUFF_TOO_SHORT;
|
||||
}
|
||||
memset(p_iotx_coap->p_auth_token, 0x00, node.value_length);
|
||||
strncpy(p_iotx_coap->p_auth_token, node.value, node.value_length);
|
||||
|
||||
memset(&node, 0x00, sizeof(lite_cjson_t));
|
||||
ret = lite_cjson_object_item(&root, "seqOffset", strlen("seqOffset"), &node);
|
||||
if (-1 == ret) {
|
||||
return IOTX_ERR_AUTH_FAILED;
|
||||
}
|
||||
p_iotx_coap->seq = node.value_int;
|
||||
|
||||
memset(&node, 0x00, sizeof(lite_cjson_t));
|
||||
ret = lite_cjson_object_item(&root, "random", strlen("random"), &node);
|
||||
if (-1 == ret) {
|
||||
return IOTX_ERR_AUTH_FAILED;
|
||||
}
|
||||
|
||||
memcpy(random, node.value, node.value_length);
|
||||
HAL_Snprintf((char *)buff, sizeof(buff), "%s,%s",
|
||||
p_iotx_coap->p_devinfo->device_secret, random);
|
||||
COAP_DEBUG("The src:%s", buff);
|
||||
utils_sha256(buff, strlen((char *)buff), key);
|
||||
memcpy(p_iotx_coap->key, key + 8, 16);
|
||||
COAP_DEBUG("The key is:");
|
||||
HEXDUMP_DEBUG(key, 32);
|
||||
COAP_DEBUG("The short key:");
|
||||
HEXDUMP_DEBUG(p_iotx_coap->key, 16);
|
||||
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
static void iotx_device_name_auth_callback(void *user, void *p_message)
|
||||
{
|
||||
int ret_code = IOTX_SUCCESS;
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
Cloud_CoAPMessage *message = (Cloud_CoAPMessage *)p_message;
|
||||
|
||||
if (NULL == user) {
|
||||
COAP_ERR("Invalid paramter, p_arg %p", user);
|
||||
return ;
|
||||
}
|
||||
p_iotx_coap = (iotx_coap_t *)user;
|
||||
|
||||
if (NULL == message) {
|
||||
COAP_ERR("Invalid paramter, message %p", message);
|
||||
return;
|
||||
}
|
||||
COAP_DEBUG("Receive response message:");
|
||||
COAP_DEBUG("* Response Code : 0x%x", message->header.code);
|
||||
COAP_DEBUG("* Payload: %s", message->payload);
|
||||
|
||||
switch (message->header.code) {
|
||||
case COAP_MSG_CODE_205_CONTENT: {
|
||||
if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
|
||||
ret_code = iotx_parse_auth_from_json((char *)message->payload, p_iotx_coap);
|
||||
} else {
|
||||
ret_code = iotx_get_token_from_json((char *)message->payload, p_iotx_coap->p_auth_token, p_iotx_coap->auth_token_len);
|
||||
}
|
||||
|
||||
if (IOTX_SUCCESS == ret_code) {
|
||||
p_iotx_coap->is_authed = IOT_TRUE;
|
||||
COAP_INFO("CoAP authenticate success!!!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR: {
|
||||
COAP_INFO("CoAP internal server error, authenticate failed, will retry it");
|
||||
HAL_SleepMs(1000);
|
||||
IOT_CoAP_DeviceNameAuth((iotx_coap_context_t *)p_iotx_coap);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static unsigned int iotx_get_coap_token(iotx_coap_t *p_iotx_coap, unsigned char *p_encoded_data)
|
||||
{
|
||||
unsigned int value = p_iotx_coap->coap_token;
|
||||
p_encoded_data[0] = (unsigned char)((value & 0x00FF) >> 0);
|
||||
p_encoded_data[1] = (unsigned char)((value & 0xFF00) >> 8);
|
||||
p_encoded_data[2] = (unsigned char)((value & 0xFF0000) >> 16);
|
||||
p_encoded_data[3] = (unsigned char)((value & 0xFF000000) >> 24);
|
||||
p_iotx_coap->coap_token++;
|
||||
return sizeof(unsigned int);
|
||||
}
|
||||
|
||||
void iotx_event_notifyer(unsigned int code, Cloud_CoAPMessage *message)
|
||||
{
|
||||
if (NULL == message) {
|
||||
COAP_ERR("Invalid paramter, message %p", message);
|
||||
return ;
|
||||
}
|
||||
|
||||
COAP_DEBUG("Error code: 0x%x, payload: %s", code, message->payload);
|
||||
switch (code) {
|
||||
case COAP_MSG_CODE_402_BAD_OPTION:
|
||||
case COAP_MSG_CODE_401_UNAUTHORIZED: {
|
||||
iotx_coap_t *p_context = NULL;
|
||||
if (NULL != message->user) {
|
||||
p_context = (iotx_coap_t *)message->user;
|
||||
p_context->is_authed = IOT_FALSE;
|
||||
IOT_CoAP_DeviceNameAuth(p_context);
|
||||
COAP_INFO("IoTx token expired, will reauthenticate");
|
||||
}
|
||||
/* TODO: call event handle to notify application */
|
||||
/* p_context->event_handle(); */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void iotx_get_well_known_handler(void *arg, void *p_response)
|
||||
{
|
||||
|
||||
int len = 0;
|
||||
unsigned char *p_payload = NULL;
|
||||
iotx_coap_resp_code_t resp_code;
|
||||
IOT_CoAP_GetMessageCode(p_response, &resp_code);
|
||||
IOT_CoAP_GetMessagePayload(p_response, &p_payload, &len);
|
||||
COAP_INFO("[APPL]: Message response code: %d", resp_code);
|
||||
COAP_INFO("[APPL]: Len: %d, Payload: %s, ", len, p_payload);
|
||||
}
|
||||
|
||||
|
||||
int iotx_get_well_known(iotx_coap_context_t *p_context)
|
||||
{
|
||||
int len = 0;
|
||||
Cloud_CoAPContext *p_coap_ctx = NULL;
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
Cloud_CoAPMessage message;
|
||||
unsigned char token[8] = {0};
|
||||
|
||||
p_iotx_coap = (iotx_coap_t *)p_context;
|
||||
p_coap_ctx = (Cloud_CoAPContext *)p_iotx_coap->p_coap_ctx;
|
||||
|
||||
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageType_set(&message, COAP_MESSAGE_TYPE_CON);
|
||||
CoAPMessageCode_set(&message, COAP_MSG_CODE_GET);
|
||||
CoAPMessageId_set(&message, Cloud_CoAPMessageId_gen(p_coap_ctx));
|
||||
len = iotx_get_coap_token(p_iotx_coap, token);
|
||||
CoAPMessageToken_set(&message, token, len);
|
||||
Cloud_CoAPMessageHandler_set(&message, iotx_get_well_known_handler);
|
||||
CoAPStrOption_add(&message, COAP_OPTION_URI_PATH, (unsigned char *)".well-known", strlen(".well-known"));
|
||||
CoAPStrOption_add(&message, COAP_OPTION_URI_PATH, (unsigned char *)"core", strlen("core"));
|
||||
CoAPUintOption_add(&message, COAP_OPTION_ACCEPT, COAP_CT_APP_LINK_FORMAT);
|
||||
CoAPMessageUserData_set(&message, (void *)p_iotx_coap);
|
||||
Cloud_CoAPMessage_send(p_coap_ctx, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
static void iotx_coap_report_rsphdl(void *arg, void *p_response)
|
||||
{
|
||||
int p_payload_len = 0;
|
||||
unsigned char *p_payload = NULL;
|
||||
iotx_coap_resp_code_t resp_code;
|
||||
|
||||
IOT_CoAP_GetMessageCode(p_response, &resp_code);
|
||||
IOT_CoAP_GetMessagePayload(p_response, &p_payload, &p_payload_len);
|
||||
COAP_DEBUG("Report response: CoAP response code = %d", resp_code);
|
||||
COAP_DEBUG("Report response: CoAP msg_len = %d", p_payload_len);
|
||||
if (p_payload_len > 0) {
|
||||
COAP_DEBUG("Report response: CoAP msg = '%.*s'", p_payload_len, p_payload);
|
||||
} else {
|
||||
COAP_WRN("Report response: CoAP response payload_len = 0");
|
||||
}
|
||||
}
|
||||
|
||||
static int coap_report_func(void *handle, const char *topic_name, int req_ack, void *data, int len)
|
||||
{
|
||||
iotx_message_t message;
|
||||
char coap_topic[100] = {0};
|
||||
(void)req_ack;
|
||||
|
||||
memset(&message, 0, sizeof(iotx_message_t));
|
||||
message.p_payload = (unsigned char *)data;
|
||||
message.payload_len = len;
|
||||
message.resp_callback = iotx_coap_report_rsphdl;
|
||||
message.msg_type = IOTX_MESSAGE_NON;
|
||||
message.content_type = IOTX_CONTENT_TYPE_JSON;
|
||||
HAL_Snprintf(coap_topic, 100, "/topic%s", topic_name);
|
||||
return IOT_CoAP_SendMessage(handle, (char *)coap_topic, &message);
|
||||
}
|
||||
|
||||
int iotx_aes_cbc_encrypt(const unsigned char *src, int len, const unsigned char *key, void *out)
|
||||
{
|
||||
char *iv = "543yhjy97ae7fyfg";
|
||||
|
||||
int len1 = len & 0xfffffff0;
|
||||
int len2 = len1 + 16;
|
||||
int pad = len2 - len;
|
||||
int ret = 0;
|
||||
|
||||
p_HAL_Aes128_t aes_e_h = HAL_Aes128_Init((unsigned char *)key, (unsigned char *)iv, HAL_AES_ENCRYPTION);
|
||||
if (len1) {
|
||||
ret = HAL_Aes128_Cbc_Encrypt(aes_e_h, src, len1 >> 4, out);
|
||||
}
|
||||
if (!ret && pad) {
|
||||
char buf[16] = {0};
|
||||
memcpy(buf, src + len1, len - len1);
|
||||
memset(buf + len - len1, pad, pad);
|
||||
ret = HAL_Aes128_Cbc_Encrypt(aes_e_h, buf, 1, (unsigned char *)out + len1);
|
||||
|
||||
}
|
||||
|
||||
HAL_Aes128_Destroy(aes_e_h);
|
||||
|
||||
COAP_DEBUG("to encrypt src: %s, len: %d", src, len2);
|
||||
return ret == 0 ? len2 : 0;
|
||||
}
|
||||
|
||||
int iotx_aes_cbc_decrypt(const unsigned char *src, int len, const unsigned char *key, void *out)
|
||||
{
|
||||
char *iv = "543yhjy97ae7fyfg";
|
||||
|
||||
p_HAL_Aes128_t aes_d_h;
|
||||
int ret = 0;
|
||||
int n = len >> 4;
|
||||
|
||||
aes_d_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_DECRYPTION);
|
||||
if (!aes_d_h) {
|
||||
COAP_INFO("fail to decrypt");
|
||||
return 0;
|
||||
}
|
||||
if (n > 1) {
|
||||
ret = HAL_Aes128_Cbc_Decrypt(aes_d_h, src, n - 1, out);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
char *out_c = (char *)out;
|
||||
int offset = n > 0 ? ((n - 1) << 4) : 0;
|
||||
out_c[offset] = 0;
|
||||
|
||||
if (aes_d_h) {
|
||||
ret = HAL_Aes128_Cbc_Decrypt(aes_d_h, src + offset, 1, out_c + offset);
|
||||
} else {
|
||||
COAP_ERR("fail to decrypt remain data");
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
char pad = out_c[len - 1];
|
||||
out_c[len - pad] = 0;
|
||||
/*
|
||||
COAP_DEBUG("decrypt data:%s, len:%d", out_c, len - pad);
|
||||
*/
|
||||
HAL_Aes128_Destroy(aes_d_h);
|
||||
return len - pad;
|
||||
}
|
||||
}
|
||||
HAL_Aes128_Destroy(aes_d_h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if AES_CFB_NOPADDING
|
||||
static int iotx_aes_cfb_encrypt(const unsigned char *src, int len, const unsigned char *key, void *out)
|
||||
{
|
||||
int ret = -1;
|
||||
char *iv = "543yhjy97ae7fyfg";
|
||||
|
||||
p_HAL_Aes128_t aes_e_h = HAL_Aes128_Init((unsigned char *)key, (unsigned char *)iv, HAL_AES_ENCRYPTION);
|
||||
ret = HAL_Aes128_Cfb_Encrypt(aes_e_h, src, len, out);
|
||||
HAL_Aes128_Destroy(aes_e_h);
|
||||
|
||||
COAP_DEBUG("to encrypt src:%s, len:%d", src, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int iotx_aes_cfb_decrypt(const unsigned char *src, int len, const unsigned char *key, void *out)
|
||||
{
|
||||
int ret = -1;
|
||||
char *iv = "543yhjy97ae7fyfg";
|
||||
|
||||
p_HAL_Aes128_t aes_d_h = HAL_Aes128_Init((unsigned char *)key, (unsigned char *)iv, HAL_AES_ENCRYPTION);
|
||||
ret = HAL_Aes128_Cfb_Decrypt(aes_d_h, src, len, out);
|
||||
HAL_Aes128_Destroy(aes_d_h);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int IOT_CoAP_DeviceNameAuth(iotx_coap_context_t *p_context)
|
||||
{
|
||||
int len = 0;
|
||||
int ret = COAP_SUCCESS;
|
||||
Cloud_CoAPContext *p_coap_ctx = NULL;
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
Cloud_CoAPMessage message;
|
||||
unsigned char *p_payload = NULL;
|
||||
unsigned char token[8] = {0};
|
||||
char sign[IOTX_SIGN_LENGTH] = {0};
|
||||
|
||||
p_iotx_coap = (iotx_coap_t *)p_context;
|
||||
if (NULL == p_iotx_coap ||
|
||||
(NULL != p_iotx_coap &&
|
||||
(NULL == p_iotx_coap->p_auth_token || NULL == p_iotx_coap->p_coap_ctx || 0 == p_iotx_coap->auth_token_len))) {
|
||||
COAP_DEBUG("Invalid paramter");
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
p_coap_ctx = (Cloud_CoAPContext *)p_iotx_coap->p_coap_ctx;
|
||||
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageType_set(&message, COAP_MESSAGE_TYPE_CON);
|
||||
CoAPMessageCode_set(&message, COAP_MSG_CODE_POST);
|
||||
CoAPMessageId_set(&message, Cloud_CoAPMessageId_gen(p_coap_ctx));
|
||||
len = iotx_get_coap_token(p_iotx_coap, token);
|
||||
CoAPMessageToken_set(&message, token, len);
|
||||
Cloud_CoAPMessageHandler_set(&message, iotx_device_name_auth_callback);
|
||||
|
||||
CoAPStrOption_add(&message, COAP_OPTION_URI_PATH, (unsigned char *)IOTX_AUTH_STR, strlen(IOTX_AUTH_STR));
|
||||
CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_JSON);
|
||||
CoAPUintOption_add(&message, COAP_OPTION_ACCEPT, COAP_CT_APP_JSON);
|
||||
|
||||
CoAPMessageUserData_set(&message, (void *)p_iotx_coap);
|
||||
|
||||
p_payload = coap_malloc(COAP_MSG_MAX_PDU_LEN);
|
||||
if (NULL == p_payload) {
|
||||
CoAPMessage_destory(&message);
|
||||
return IOTX_ERR_NO_MEM;
|
||||
}
|
||||
memset(p_payload, 0x00, COAP_MSG_MAX_PDU_LEN);
|
||||
|
||||
if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
|
||||
iotx_calc_sign_with_seq(p_iotx_coap->p_devinfo->device_secret, p_iotx_coap->p_devinfo->device_id,
|
||||
p_iotx_coap->p_devinfo->device_name, p_iotx_coap->p_devinfo->product_key, p_iotx_coap->seq, sign);
|
||||
HAL_Snprintf((char *)p_payload, COAP_MSG_MAX_PDU_LEN,
|
||||
IOTX_AUTH_DEVICENAME_STR_WITH_SEQ,
|
||||
p_iotx_coap->p_devinfo->product_key,
|
||||
p_iotx_coap->p_devinfo->device_name,
|
||||
p_iotx_coap->p_devinfo->device_id,
|
||||
sign, p_iotx_coap->seq);
|
||||
|
||||
} else {
|
||||
iotx_calc_sign(p_iotx_coap->p_devinfo->device_secret, p_iotx_coap->p_devinfo->device_id,
|
||||
p_iotx_coap->p_devinfo->device_name, p_iotx_coap->p_devinfo->product_key, sign);
|
||||
HAL_Snprintf((char *)p_payload, COAP_MSG_MAX_PDU_LEN,
|
||||
IOTX_AUTH_DEVICENAME_STR,
|
||||
p_iotx_coap->p_devinfo->product_key,
|
||||
p_iotx_coap->p_devinfo->device_name,
|
||||
p_iotx_coap->p_devinfo->device_id,
|
||||
sign);
|
||||
}
|
||||
CoAPMessagePayload_set(&message, p_payload, strlen((char *)p_payload));
|
||||
COAP_DEBUG("The payload is: %s", message.payload);
|
||||
COAP_DEBUG("Send authentication message to server");
|
||||
ret = Cloud_CoAPMessage_send(p_coap_ctx, &message);
|
||||
coap_free(p_payload);
|
||||
CoAPMessage_destory(&message);
|
||||
|
||||
if (COAP_SUCCESS != ret) {
|
||||
COAP_DEBUG("Send authentication message to server failed, ret = %d", ret);
|
||||
return IOTX_ERR_SEND_MSG_FAILED;
|
||||
}
|
||||
|
||||
ret = Cloud_CoAPMessage_recv(p_coap_ctx, CONFIG_COAP_AUTH_TIMEOUT, 2);
|
||||
if (0 < ret && !p_iotx_coap->is_authed) {
|
||||
COAP_INFO("CoAP authenticate failed");
|
||||
return IOTX_ERR_AUTH_FAILED;
|
||||
}
|
||||
|
||||
|
||||
iotx_set_report_func(coap_report_func);
|
||||
/* report module id */
|
||||
ret = iotx_report_mid(p_context);
|
||||
if (SUCCESS_RETURN != ret) {
|
||||
COAP_WRN("Send ModuleId message to server(CoAP) failed, ret = %d", ret);
|
||||
}
|
||||
/* report device information */
|
||||
ret = iotx_report_devinfo(p_context);
|
||||
if (SUCCESS_RETURN != ret) {
|
||||
COAP_WRN("Send devinfo message to server(CoAP) failed, ret = %d", ret);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* report firmware version */
|
||||
ret = iotx_report_firmware_version(p_context);
|
||||
if (SUCCESS_RETURN != ret) {
|
||||
COAP_DEBUG("Send firmware message to server(CoAP) failed, ret = %d", ret);
|
||||
return IOTX_ERR_SEND_MSG_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
static int iotx_split_path_2_option(char *uri, Cloud_CoAPMessage *message)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
char *pstr = NULL;
|
||||
char path[COAP_MSG_MAX_PATH_LEN] = {0};
|
||||
|
||||
if (NULL == uri || NULL == message) {
|
||||
COAP_ERR("Invalid paramter p_path %p, p_message %p", uri, message);
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (IOTX_URI_MAX_LEN < strlen(uri)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
|
||||
return IOTX_ERR_URI_TOO_LOOG;
|
||||
}
|
||||
COAP_DEBUG("The uri is %s", uri);
|
||||
ptr = pstr = uri;
|
||||
while ('\0' != *ptr) {
|
||||
if ('/' == *ptr) {
|
||||
if (ptr != pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, ptr - pstr);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)(ptr - pstr));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
pstr = ptr + 1;
|
||||
|
||||
}
|
||||
if ('\0' == *(ptr + 1) && '\0' != *pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, sizeof(path) - 1);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)strlen(path));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
ptr ++;
|
||||
}
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t IOT_CoAP_GetCurToken(iotx_coap_context_t *p_context)
|
||||
{
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
|
||||
if (p_context == NULL) {
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
p_iotx_coap = (iotx_coap_t *)p_context;
|
||||
|
||||
return p_iotx_coap->coap_token;
|
||||
}
|
||||
|
||||
int IOT_CoAP_SendMessage(iotx_coap_context_t *p_context, char *p_path, iotx_message_t *p_message)
|
||||
{
|
||||
|
||||
int len = 0;
|
||||
int ret = IOTX_SUCCESS;
|
||||
Cloud_CoAPContext *p_coap_ctx = NULL;
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
Cloud_CoAPMessage message;
|
||||
unsigned char token[8] = {0};
|
||||
unsigned char *payload = NULL;
|
||||
|
||||
p_iotx_coap = (iotx_coap_t *)p_context;
|
||||
|
||||
if (NULL == p_context || NULL == p_path || NULL == p_message ||
|
||||
(NULL != p_iotx_coap && NULL == p_iotx_coap->p_coap_ctx)) {
|
||||
COAP_ERR("Invalid paramter p_context %p, p_uri %p, p_message %p",
|
||||
p_context, p_path, p_message);
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
#ifdef INFRA_LOG_NETWORK_PAYLOAD
|
||||
COAP_INFO("Upstream Topic: '%s'", p_path);
|
||||
COAP_INFO("Upstream Payload:");
|
||||
iotx_facility_json_print((const char *)p_message->p_payload, LOG_INFO_LEVEL, '>');
|
||||
#endif
|
||||
|
||||
/* as this function only support POST request message, type ACK and RST shall be considered error parameters */
|
||||
if (p_message->msg_type != IOTX_MESSAGE_CON && p_message->msg_type != IOTX_MESSAGE_NON) {
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (p_message->payload_len >= COAP_MSG_MAX_PDU_LEN) {
|
||||
COAP_ERR("The payload length %d is too loog", p_message->payload_len);
|
||||
return IOTX_ERR_MSG_TOO_LOOG;
|
||||
}
|
||||
|
||||
p_coap_ctx = (Cloud_CoAPContext *)p_iotx_coap->p_coap_ctx;
|
||||
if (p_iotx_coap->is_authed) {
|
||||
|
||||
/* CoAPMessage_init(&message); */
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageType_set(&message, p_message->msg_type);
|
||||
CoAPMessageCode_set(&message, COAP_MSG_CODE_POST);
|
||||
CoAPMessageId_set(&message, Cloud_CoAPMessageId_gen(p_coap_ctx));
|
||||
len = iotx_get_coap_token(p_iotx_coap, token);
|
||||
CoAPMessageToken_set(&message, token, len);
|
||||
CoAPMessageUserData_set(&message, (void *)p_message->user_data);
|
||||
Cloud_CoAPMessageHandler_set(&message, p_message->resp_callback);
|
||||
|
||||
ret = iotx_split_path_2_option(p_path, &message);
|
||||
if (IOTX_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IOTX_CONTENT_TYPE_CBOR == p_message->content_type) {
|
||||
CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_CBOR);
|
||||
CoAPUintOption_add(&message, COAP_OPTION_ACCEPT, COAP_CT_APP_OCTET_STREAM);
|
||||
} else {
|
||||
CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_JSON);
|
||||
CoAPUintOption_add(&message, COAP_OPTION_ACCEPT, COAP_CT_APP_OCTET_STREAM);
|
||||
}
|
||||
CoAPStrOption_add(&message, COAP_OPTION_AUTH_TOKEN,
|
||||
(unsigned char *)p_iotx_coap->p_auth_token, strlen(p_iotx_coap->p_auth_token));
|
||||
if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
|
||||
unsigned char buff[32] = {0};
|
||||
unsigned char seq[33] = {0};
|
||||
HAL_Snprintf((char *)buff, sizeof(buff) - 1, "%d", p_iotx_coap->seq++);
|
||||
len = iotx_aes_cbc_encrypt(buff, strlen((char *)buff), p_iotx_coap->key, seq);
|
||||
if (0 < len) {
|
||||
CoAPStrOption_add(&message, COAP_OPTION_SEQ, (unsigned char *)seq, len);
|
||||
} else {
|
||||
COAP_INFO("Encrypt seq failed");
|
||||
}
|
||||
HEXDUMP_DEBUG(seq, len);
|
||||
|
||||
payload = (unsigned char *)coap_malloc(COAP_MSG_MAX_PDU_LEN);
|
||||
if (NULL == payload) {
|
||||
return IOTX_ERR_NO_MEM;
|
||||
}
|
||||
memset(payload, 0x00, COAP_MSG_MAX_PDU_LEN);
|
||||
len = iotx_aes_cbc_encrypt(p_message->p_payload, p_message->payload_len, p_iotx_coap->key, payload);
|
||||
if (0 == len) {
|
||||
coap_free(payload);
|
||||
payload = NULL;
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
HEXDUMP_DEBUG(payload, len);
|
||||
CoAPMessagePayload_set(&message, payload, len);
|
||||
} else {
|
||||
CoAPMessagePayload_set(&message, p_message->p_payload, p_message->payload_len);
|
||||
}
|
||||
ret = Cloud_CoAPMessage_send(p_coap_ctx, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
if (NULL != payload) {
|
||||
coap_free(payload);
|
||||
payload = NULL;
|
||||
}
|
||||
|
||||
if (COAP_ERROR_DATA_SIZE == ret) {
|
||||
return IOTX_ERR_MSG_TOO_LOOG;
|
||||
}
|
||||
|
||||
return IOTX_SUCCESS;
|
||||
} else {
|
||||
COAP_ERR("The client [%s/%s] still un-authorized yet, return %d",
|
||||
p_iotx_coap->p_devinfo->product_key,
|
||||
p_iotx_coap->p_devinfo->device_name,
|
||||
IOTX_ERR_NOT_AUTHED
|
||||
);
|
||||
return IOTX_ERR_NOT_AUTHED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int IOT_CoAP_GetMessagePayload(void *p_message, unsigned char **pp_payload, int *p_len)
|
||||
{
|
||||
Cloud_CoAPMessage *message = NULL;
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
|
||||
if (NULL == p_message || NULL == pp_payload || NULL == p_len || NULL == g_coap_context) {
|
||||
COAP_ERR("Invalid parameter: p_message=%p, pp_payload=%p, p_len=%p",
|
||||
p_message, pp_payload, p_len);
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
p_iotx_coap = (iotx_coap_t *)g_coap_context;
|
||||
message = (Cloud_CoAPMessage *)p_message;
|
||||
|
||||
COAP_DEBUG("message->payload: %p", message->payload);
|
||||
COAP_DEBUG("message->payloadlen: %d", message->payloadlen);
|
||||
|
||||
if (message->payloadlen >= COAP_MSG_MAX_PDU_LEN) {
|
||||
COAP_ERR("Invalid parameter: message->payloadlen(%d) out of [0, %d]",
|
||||
message->payloadlen, COAP_MSG_MAX_PDU_LEN);
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
|
||||
int len = 0;
|
||||
unsigned char *payload = NULL;
|
||||
payload = coap_malloc(COAP_MSG_MAX_PDU_LEN);
|
||||
if (NULL == payload) {
|
||||
return IOTX_ERR_NO_MEM;
|
||||
}
|
||||
memset(payload, 0x00, COAP_MSG_MAX_PDU_LEN);
|
||||
|
||||
HEXDUMP_DEBUG(message->payload, message->payloadlen);
|
||||
|
||||
len = iotx_aes_cbc_decrypt(message->payload, message->payloadlen, p_iotx_coap->key, payload);
|
||||
if (len > 0) {
|
||||
COAP_DEBUG("payload: %.*s, len %d", len, payload, len);
|
||||
}
|
||||
if (len != 0) {
|
||||
memcpy(message->payload, payload, len);
|
||||
message->payloadlen = len;
|
||||
HEXDUMP_DEBUG(payload, len);
|
||||
}
|
||||
|
||||
coap_free(payload);
|
||||
}
|
||||
|
||||
*pp_payload = message->payload;
|
||||
*p_len = message->payloadlen;
|
||||
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
int IOT_CoAP_GetMessageToken(void *p_message, unsigned int *token)
|
||||
{
|
||||
|
||||
Cloud_CoAPMessage *message = NULL;
|
||||
|
||||
if (NULL == p_message || NULL == token) {
|
||||
COAP_ERR("Invalid paramter p_message %p, token= %p", p_message, token);
|
||||
return -1;
|
||||
}
|
||||
message = (Cloud_CoAPMessage *)p_message;
|
||||
|
||||
*token = ((unsigned int)(message->token[3]) & 0xff) << 24;
|
||||
*token += ((unsigned int)(message->token[2]) & 0xff) << 16;
|
||||
*token += ((unsigned int)(message->token[1]) & 0xff) << 8;
|
||||
*token += ((unsigned int)(message->token[0]) & 0xff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IOT_CoAP_GetMessageCode(void *p_message, iotx_coap_resp_code_t *p_resp_code)
|
||||
{
|
||||
Cloud_CoAPMessage *message = NULL;
|
||||
|
||||
if (NULL == p_message || NULL == p_resp_code) {
|
||||
COAP_ERR("Invalid paramter p_message %p, p_resp_code %p",
|
||||
p_message, p_resp_code);
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
message = (Cloud_CoAPMessage *)p_message;
|
||||
*p_resp_code = (iotx_coap_resp_code_t) message->header.code;
|
||||
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned int iotx_get_seq(void)
|
||||
{
|
||||
HAL_Srandom((unsigned int)HAL_UptimeMs());
|
||||
return HAL_Random(0xffffffff) % 10000;
|
||||
}
|
||||
|
||||
iotx_coap_context_t *IOT_CoAP_Init(iotx_coap_config_t *p_config)
|
||||
{
|
||||
Cloud_CoAPInitParam param;
|
||||
char url[128] = {0};
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
|
||||
if (NULL == p_config) {
|
||||
COAP_ERR("Invalid paramter p_config %p", p_config);
|
||||
return NULL;
|
||||
}
|
||||
if (NULL == p_config->p_devinfo) {
|
||||
COAP_ERR("Invalid paramter p_devinfo %p", p_config->p_devinfo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p_iotx_coap = coap_malloc(sizeof(iotx_coap_t));
|
||||
if (NULL == p_iotx_coap) {
|
||||
COAP_ERR(" Allocate memory for iotx_coap_context_t failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(p_iotx_coap, 0x00, sizeof(iotx_coap_t));
|
||||
|
||||
p_iotx_coap->p_auth_token = coap_malloc(IOTX_AUTH_TOKEN_LEN);
|
||||
if (NULL == p_iotx_coap->p_auth_token) {
|
||||
COAP_ERR(" Allocate memory for auth token failed");
|
||||
goto err;
|
||||
}
|
||||
memset(p_iotx_coap->p_auth_token, 0x00, IOTX_AUTH_TOKEN_LEN);
|
||||
|
||||
/*Set the client isn't authed*/
|
||||
p_iotx_coap->is_authed = IOT_FALSE;
|
||||
p_iotx_coap->auth_token_len = IOTX_AUTH_TOKEN_LEN;
|
||||
|
||||
/*Get deivce information*/
|
||||
p_iotx_coap->p_devinfo = coap_malloc(sizeof(iotx_deviceinfo_t));
|
||||
if (NULL == p_iotx_coap->p_devinfo) {
|
||||
COAP_ERR(" Allocate memory for iotx_deviceinfo_t failed");
|
||||
goto err;
|
||||
}
|
||||
memset(p_iotx_coap->p_devinfo, 0x00, sizeof(iotx_deviceinfo_t));
|
||||
|
||||
/*It should be implement by the user*/
|
||||
if (NULL != p_config->p_devinfo) {
|
||||
memset(p_iotx_coap->p_devinfo, 0x00, sizeof(iotx_deviceinfo_t));
|
||||
strncpy(p_iotx_coap->p_devinfo->device_id, p_config->p_devinfo->device_id, strlen(p_config->p_devinfo->device_id));
|
||||
strncpy(p_iotx_coap->p_devinfo->product_key, p_config->p_devinfo->product_key,
|
||||
strlen(p_config->p_devinfo->product_key));
|
||||
strncpy(p_iotx_coap->p_devinfo->device_secret, p_config->p_devinfo->device_secret,
|
||||
strlen(p_config->p_devinfo->device_secret));
|
||||
strncpy(p_iotx_coap->p_devinfo->device_name, p_config->p_devinfo->device_name,
|
||||
strlen(p_config->p_devinfo->device_name));
|
||||
}
|
||||
|
||||
/*Init coap token*/
|
||||
p_iotx_coap->coap_token = IOTX_COAP_INIT_TOKEN;
|
||||
p_iotx_coap->seq = iotx_get_seq();
|
||||
memset(p_iotx_coap->key, 0x00, sizeof(p_iotx_coap->key));
|
||||
|
||||
/*Create coap context*/
|
||||
memset(¶m, 0x00, sizeof(Cloud_CoAPInitParam));
|
||||
|
||||
if (NULL != p_config->p_url) {
|
||||
param.url = p_config->p_url;
|
||||
} else {
|
||||
HAL_Snprintf(url, sizeof(url), IOTX_COAP_ONLINE_PSK_SERVER_URL, p_iotx_coap->p_devinfo->product_key);
|
||||
param.url = url;
|
||||
COAP_INFO("Using default CoAP server: %s", url);
|
||||
}
|
||||
param.maxcount = IOTX_LIST_MAX_ITEM;
|
||||
param.notifier = (Cloud_CoAPEventNotifier)iotx_event_notifyer;
|
||||
param.waittime = p_config->wait_time_ms;
|
||||
p_iotx_coap->p_coap_ctx = Cloud_CoAPContext_create(¶m);
|
||||
if (NULL == p_iotx_coap->p_coap_ctx) {
|
||||
COAP_ERR(" Create coap context failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*Register the event handle to notify the application */
|
||||
p_iotx_coap->event_handle = p_config->event_handle;
|
||||
|
||||
g_coap_context = (iotx_coap_context_t *)p_iotx_coap;
|
||||
return (iotx_coap_context_t *)p_iotx_coap;
|
||||
err:
|
||||
/* Error, release the memory */
|
||||
if (NULL != p_iotx_coap) {
|
||||
if (NULL != p_iotx_coap->p_devinfo) {
|
||||
coap_free(p_iotx_coap->p_devinfo);
|
||||
}
|
||||
if (NULL != p_iotx_coap->p_auth_token) {
|
||||
coap_free(p_iotx_coap->p_auth_token);
|
||||
}
|
||||
if (NULL != p_iotx_coap->p_coap_ctx) {
|
||||
Cloud_CoAPContext_free(p_iotx_coap->p_coap_ctx);
|
||||
}
|
||||
|
||||
p_iotx_coap->auth_token_len = 0;
|
||||
p_iotx_coap->is_authed = IOT_FALSE;
|
||||
coap_free(p_iotx_coap);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void IOT_CoAP_Deinit(iotx_coap_context_t **pp_context)
|
||||
{
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
|
||||
if (NULL != pp_context && NULL != *pp_context) {
|
||||
p_iotx_coap = (iotx_coap_t *)*pp_context;
|
||||
p_iotx_coap->is_authed = IOT_FALSE;
|
||||
p_iotx_coap->auth_token_len = 0;
|
||||
p_iotx_coap->coap_token = IOTX_COAP_INIT_TOKEN;
|
||||
|
||||
if (NULL != p_iotx_coap->p_auth_token) {
|
||||
coap_free(p_iotx_coap->p_auth_token);
|
||||
p_iotx_coap->p_auth_token = NULL;
|
||||
}
|
||||
|
||||
if (NULL != p_iotx_coap->p_devinfo) {
|
||||
coap_free(p_iotx_coap->p_devinfo);
|
||||
p_iotx_coap->p_devinfo = NULL;
|
||||
}
|
||||
|
||||
if (NULL != p_iotx_coap->p_coap_ctx) {
|
||||
Cloud_CoAPContext_free(p_iotx_coap->p_coap_ctx);
|
||||
p_iotx_coap->p_coap_ctx = NULL;
|
||||
}
|
||||
coap_free(p_iotx_coap);
|
||||
*pp_context = NULL;
|
||||
g_coap_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int IOT_CoAP_Yield(iotx_coap_context_t *p_context)
|
||||
{
|
||||
iotx_coap_t *p_iotx_coap = NULL;
|
||||
p_iotx_coap = (iotx_coap_t *)p_context;
|
||||
if (NULL == p_iotx_coap || (NULL != p_iotx_coap && NULL == p_iotx_coap->p_coap_ctx)) {
|
||||
COAP_ERR("Invalid paramter");
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return Cloud_CoAPMessage_cycle(p_iotx_coap->p_coap_ctx);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef __IOTX_COAP_CONFIG__
|
||||
#define __IOTX_COAP_CONFIG__
|
||||
|
||||
#define COAP_MSG_MAX_TOKEN_LEN 8
|
||||
#define COAP_MSG_MAX_OPTION_NUM 12
|
||||
#define COAP_MSG_MAX_PATH_LEN 128
|
||||
#ifndef COAP_LARGE_MEMORY_SUPPORT
|
||||
#define COAP_MSG_MAX_PDU_LEN 1280
|
||||
#else
|
||||
#define COAP_MSG_MAX_PDU_LEN 4096
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_COAP_AUTH_TIMEOUT
|
||||
#define CONFIG_COAP_AUTH_TIMEOUT (3 * 1000)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __IOTX_COAP_INTERNAL__
|
||||
#define __IOTX_COAP_INTERNAL__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "infra_string.h"
|
||||
#include "infra_compat.h"
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_log.h"
|
||||
#include "infra_json_parser.h"
|
||||
#include "infra_cjson.h"
|
||||
#include "infra_list.h"
|
||||
#include "infra_md5.h"
|
||||
#include "infra_sha256.h"
|
||||
#include "infra_report.h"
|
||||
#include "iotx_coap_config.h"
|
||||
#include "coap_wrapper.h"
|
||||
#include "iotx_coap_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*CoAP Content Type*/
|
||||
#define COAP_CT_TEXT_PLAIN 0 /* text/plain (UTF-8) */
|
||||
#define COAP_CT_APP_LINK_FORMAT 40 /* application/link-format */
|
||||
#define COAP_CT_APP_XML 41 /* application/xml */
|
||||
#define COAP_CT_APP_OCTET_STREAM 42 /* application/octet-stream */
|
||||
#define COAP_CT_APP_RDF_XML 43 /* application/rdf+xml */
|
||||
#define COAP_CT_APP_EXI 47 /* application/exi */
|
||||
#define COAP_CT_APP_JSON 50 /* application/json */
|
||||
#define COAP_CT_APP_CBOR 60 /* application/cbor */
|
||||
|
||||
/*CoAP option types. */
|
||||
#define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */
|
||||
#define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */
|
||||
#define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */
|
||||
#define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */
|
||||
#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none)*/
|
||||
#define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */
|
||||
#define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */
|
||||
#define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */
|
||||
#define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */
|
||||
#define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */
|
||||
#define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */
|
||||
#define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */
|
||||
#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */
|
||||
#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */
|
||||
#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */
|
||||
#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1024 B, (none) */
|
||||
#define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */
|
||||
#define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */
|
||||
#define COAP_OPTION_AUTH_TOKEN 61 /* C, String, 1-255B, (none)*/
|
||||
|
||||
#define COAP_PERM_NONE 0x0000
|
||||
#define COAP_PERM_GET 0x0001
|
||||
#define COAP_PERM_POST 0x0002
|
||||
#define COAP_PERM_PUT 0x0004
|
||||
#define COAP_PERM_DELETE 0x0008
|
||||
#define COAP_PERM_OBSERVE 0x0100
|
||||
|
||||
/*CoAP Message types*/
|
||||
#define COAP_MESSAGE_TYPE_CON 0
|
||||
#define COAP_MESSAGE_TYPE_NON 1
|
||||
#define COAP_MESSAGE_TYPE_ACK 2
|
||||
#define COAP_MESSAGE_TYPE_RST 3
|
||||
|
||||
/* CoAP module error code base */
|
||||
#define COAP_ERROR_BASE (1<<8)
|
||||
#define COAP_ERROR_DTLS_BASE (1<<16)
|
||||
|
||||
/* CoAP base error code */
|
||||
#define COAP_SUCCESS (0) /* Successful */
|
||||
#define COAP_ERROR_INVALID_PARAM (COAP_ERROR_BASE | 1) /* Invalid Parameter */
|
||||
#define COAP_ERROR_NULL (COAP_ERROR_BASE | 2) /* Null Pointer */
|
||||
#define COAP_ERROR_MALLOC (COAP_ERROR_BASE | 3)
|
||||
#define COAP_ERROR_INVALID_LENGTH (COAP_ERROR_BASE | 4) /* Invalid Length */
|
||||
#define COAP_ERROR_DATA_SIZE (COAP_ERROR_BASE | 5) /* Data size exceeds limit */
|
||||
#define COAP_ERROR_INVALID_URI (COAP_ERROR_BASE | 6)
|
||||
#define COAP_ERROR_NOT_FOUND (COAP_ERROR_BASE | 7)
|
||||
#define COAP_ERROR_NET_INIT_FAILED (COAP_ERROR_BASE | 8)
|
||||
#define COAP_ERROR_INTERNAL (COAP_ERROR_BASE | 9) /* Internal Error */
|
||||
#define COAP_ERROR_WRITE_FAILED (COAP_ERROR_BASE | 10)
|
||||
#define COAP_ERROR_READ_FAILED (COAP_ERROR_BASE | 11)
|
||||
#define COAP_ERROR_ENCRYPT_FAILED (COAP_ERROR_BASE | 12)
|
||||
#define COAP_ERROR_UNSUPPORTED (COAP_ERROR_BASE | 13)
|
||||
#define COAP_ERROR_OBJ_ALREADY_EXIST (COAP_ERROR_BASE | 14)
|
||||
|
||||
#define COAP_MSG_CODE_DEF(N) (((N)/100 << 5) | (N)%100)
|
||||
|
||||
/*CoAP Message codes*/
|
||||
typedef enum {
|
||||
/* CoAP Empty Message */
|
||||
COAP_MSG_CODE_EMPTY_MESSAGE = COAP_MSG_CODE_DEF(0), /* Mapping to CoAP code 0.00 */
|
||||
|
||||
/* CoAP Method Codes */
|
||||
COAP_MSG_CODE_GET = COAP_MSG_CODE_DEF(1), /* CoAP Get method */
|
||||
COAP_MSG_CODE_POST = COAP_MSG_CODE_DEF(2), /* CoAP Post method */
|
||||
COAP_MSG_CODE_PUT = COAP_MSG_CODE_DEF(3), /* CoAP Put method */
|
||||
COAP_MSG_CODE_DELETE = COAP_MSG_CODE_DEF(4), /* CoAP Delete method */
|
||||
|
||||
/* CoAP Success Response Codes */
|
||||
COAP_MSG_CODE_201_CREATED = COAP_MSG_CODE_DEF(201), /* Mapping to CoAP code 2.01, Hex:0x41, Created */
|
||||
COAP_MSG_CODE_202_DELETED = COAP_MSG_CODE_DEF(202), /* Mapping to CoAP code 2.02, Hex:0x42, Deleted*/
|
||||
COAP_MSG_CODE_203_VALID = COAP_MSG_CODE_DEF(203), /* Mapping to CoAP code 2.03, Hex:0x43, Valid*/
|
||||
COAP_MSG_CODE_204_CHANGED = COAP_MSG_CODE_DEF(204), /* Mapping to CoAP code 2.04, Hex:0x44, Changed*/
|
||||
COAP_MSG_CODE_205_CONTENT = COAP_MSG_CODE_DEF(205), /* Mapping to CoAP code 2.05, Hex:0x45, Content*/
|
||||
COAP_MSG_CODE_231_CONTINUE = COAP_MSG_CODE_DEF(231), /* Mapping to CoAP code 2.31, Hex:0x5F, Continue*/
|
||||
|
||||
/* CoAP Client Error Response Codes */
|
||||
COAP_MSG_CODE_400_BAD_REQUEST = COAP_MSG_CODE_DEF(400), /* Mapping to CoAP code 4.00, Hex:0x80, Bad Request */
|
||||
COAP_MSG_CODE_401_UNAUTHORIZED = COAP_MSG_CODE_DEF(401), /* Mapping to CoAP code 4.01, Hex:0x81, Unauthorized */
|
||||
COAP_MSG_CODE_402_BAD_OPTION = COAP_MSG_CODE_DEF(402), /* Mapping to CoAP code 4.02, Hex:0x82, Bad Option */
|
||||
COAP_MSG_CODE_403_FORBIDDEN = COAP_MSG_CODE_DEF(403), /* Mapping to CoAP code 4.03, Hex:0x83, Forbidden */
|
||||
COAP_MSG_CODE_404_NOT_FOUND = COAP_MSG_CODE_DEF(404), /* Mapping to CoAP code 4.04, Hex:0x84, Not Found */
|
||||
COAP_MSG_CODE_405_METHOD_NOT_ALLOWED = COAP_MSG_CODE_DEF(405), /* Mapping to CoAP code 4.05, Hex:0x85, Method Not Allowed */
|
||||
COAP_MSG_CODE_406_NOT_ACCEPTABLE = COAP_MSG_CODE_DEF(406), /* Mapping to CoAP code 4.06, Hex:0x86, Not Acceptable */
|
||||
COAP_MSG_CODE_408_REQUEST_ENTITY_INCOMPLETE = COAP_MSG_CODE_DEF(408), /* Mapping to CoAP code 4.08, Hex:0x88, Request Entity Incomplete */
|
||||
COAP_MSG_CODE_412_PRECONDITION_FAILED = COAP_MSG_CODE_DEF(412), /* Mapping to CoAP code 4.12, Hex:0x8C, Precondition Failed */
|
||||
COAP_MSG_CODE_413_REQUEST_ENTITY_TOO_LARGE = COAP_MSG_CODE_DEF(413), /* Mapping to CoAP code 4.13, Hex:0x8D, Request Entity Too Large */
|
||||
COAP_MSG_CODE_415_UNSUPPORTED_CONTENT_FORMAT = COAP_MSG_CODE_DEF(415), /* Mapping to CoAP code 4.15, Hex:0x8F, Unsupported Content-Format */
|
||||
|
||||
/* CoAP Server Error Response Codes */
|
||||
COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR = COAP_MSG_CODE_DEF(500), /* Mapping to CoAP code 5.00, Hex:0xA0, Internal Server Error */
|
||||
COAP_MSG_CODE_501_NOT_IMPLEMENTED = COAP_MSG_CODE_DEF(501), /* Mapping to CoAP code 5.01, Hex:0xA1, Not Implemented */
|
||||
COAP_MSG_CODE_502_BAD_GATEWAY = COAP_MSG_CODE_DEF(502), /* Mapping to CoAP code 5.02, Hex:0xA2, Bad Gateway */
|
||||
COAP_MSG_CODE_503_SERVICE_UNAVAILABLE = COAP_MSG_CODE_DEF(503), /* Mapping to CoAP code 5.03, Hex:0xA3, Service Unavailable */
|
||||
COAP_MSG_CODE_504_GATEWAY_TIMEOUT = COAP_MSG_CODE_DEF(504), /* Mapping to CoAP code 5.04, Hex:0xA4, Gateway Timeout */
|
||||
COAP_MSG_CODE_505_PROXYING_NOT_SUPPORTED = COAP_MSG_CODE_DEF(505) /* Mapping to CoAP code 5.05, Hex:0xA5, Proxying Not Supported */
|
||||
|
||||
} CoAPMessageCode;
|
||||
|
||||
typedef enum {
|
||||
COAP_REQUEST_SUCCESS = 0,
|
||||
COAP_RECV_RESP_TIMEOUT,
|
||||
COAP_RECV_RESP_SUC,
|
||||
} CoAPReqResult;
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
unsigned char *data;
|
||||
} CoAPLenString;
|
||||
|
||||
typedef struct {
|
||||
unsigned char version : 2;
|
||||
unsigned char type : 2;
|
||||
unsigned char tokenlen : 4;
|
||||
unsigned char code;
|
||||
unsigned short msgid;
|
||||
} CoAPMsgHeader;
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned short num;
|
||||
unsigned short len;
|
||||
unsigned char *val;
|
||||
} CoAPMsgOption;
|
||||
|
||||
typedef void CoAPContext;
|
||||
typedef struct CoAPMessage CoAPMessage;
|
||||
|
||||
typedef void (*CoAPSendMsgHandler)(CoAPContext *context, CoAPReqResult result, void *userdata, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
|
||||
typedef void (*CoAPEventNotifier)(unsigned int event, NetworkAddr *remote, void *message);
|
||||
|
||||
typedef void (*CoAPRecvMsgHandler)(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *message);
|
||||
|
||||
typedef int (*CoAPDataEncrypt)(CoAPContext *context, const char *paths, NetworkAddr *addr, CoAPMessage *message,
|
||||
CoAPLenString *src, CoAPLenString *dest);
|
||||
typedef void (*CoAPRespMsgHandler)(void *data, void *message);
|
||||
|
||||
struct CoAPMessage {
|
||||
CoAPMsgHeader header;
|
||||
unsigned char token[COAP_MSG_MAX_TOKEN_LEN];
|
||||
CoAPMsgOption options[COAP_MSG_MAX_OPTION_NUM];
|
||||
unsigned char optcount;
|
||||
unsigned char optdelta;
|
||||
unsigned short payloadlen;
|
||||
unsigned char *payload;
|
||||
CoAPSendMsgHandler handler;
|
||||
CoAPRespMsgHandler resp;
|
||||
void *user;
|
||||
int keep;
|
||||
};
|
||||
|
||||
|
||||
/* CoAP message options APIs*/
|
||||
extern int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short datalen);
|
||||
|
||||
extern int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short *datalen);
|
||||
|
||||
extern int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned int data);
|
||||
|
||||
extern int CoAPUintOption_get(CoAPMessage *message,
|
||||
unsigned short optnum,
|
||||
unsigned int *data);
|
||||
|
||||
extern int CoAPOption_present(CoAPMessage *message, unsigned short option);
|
||||
|
||||
|
||||
|
||||
extern int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid);
|
||||
|
||||
extern int CoAPMessageType_set(CoAPMessage *message, unsigned char type);
|
||||
|
||||
extern int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code);
|
||||
|
||||
extern int CoAPMessageCode_get(CoAPMessage *message, CoAPMessageCode *code);
|
||||
|
||||
extern int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
|
||||
unsigned char tokenlen);
|
||||
|
||||
extern int CoAPMessageUserData_set(CoAPMessage *message, void *userdata);
|
||||
|
||||
extern int CoAPMessageKeep_Set(CoAPMessage *message, int keep);
|
||||
|
||||
extern int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
|
||||
unsigned short payloadlen);
|
||||
|
||||
extern int CoAPMessageHandler_set(CoAPMessage *message, CoAPSendMsgHandler handler);
|
||||
|
||||
extern int CoAPMessage_init(CoAPMessage *message);
|
||||
|
||||
extern int CoAPMessage_destory(CoAPMessage *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __COAP_DESERIALIZE_H__
|
||||
#define __COAP_DESERIALIZE_H__
|
||||
#include <stdio.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
int CoAPDeserialize_Header(CoAPMessage *msg, unsigned char *buf)
|
||||
{
|
||||
msg->header.version = ((buf[0] >> 6) & 0x03);
|
||||
msg->header.type = ((buf[0] >> 4) & 0x03);
|
||||
msg->header.tokenlen = (buf[0] & 0x0F);
|
||||
msg->header.code = buf[1];
|
||||
msg->header.msgid = buf[2] << 8;
|
||||
msg->header.msgid += buf[3];
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Token(CoAPMessage *msg, unsigned char *buf)
|
||||
{
|
||||
memcpy(msg->token, buf, msg->header.tokenlen);
|
||||
return msg->header.tokenlen;
|
||||
}
|
||||
|
||||
static int CoAPDeserialize_Option(CoAPMsgOption *option, unsigned char *buf, unsigned short *predeltas)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short optdelta = 0;
|
||||
unsigned short optlen = 0;
|
||||
unsigned short predelta = 0;
|
||||
|
||||
optdelta = (*ptr & 0xF0) >> 4;
|
||||
optlen = (*ptr & 0x0F);
|
||||
ptr++;
|
||||
|
||||
predelta = *predeltas;
|
||||
if (13 == optdelta) {
|
||||
predelta += 13 + *ptr;
|
||||
ptr ++;
|
||||
|
||||
} else if (14 == optdelta) {
|
||||
predelta += 269;
|
||||
predelta += (*ptr << 8);
|
||||
predelta += *(ptr + 1);
|
||||
ptr += 2;
|
||||
} else {
|
||||
predelta += optdelta;
|
||||
}
|
||||
option->num = predelta;
|
||||
|
||||
if (13 == optlen) {
|
||||
optlen = 13 + *ptr;
|
||||
ptr ++;
|
||||
} else if (14 == optlen) {
|
||||
optlen = 269;
|
||||
optlen += (*ptr << 8);
|
||||
optlen += *(ptr + 1);
|
||||
ptr += 2;
|
||||
}
|
||||
option->len = optlen;
|
||||
|
||||
option->val = ptr;
|
||||
*predeltas = option->num;
|
||||
|
||||
return (ptr - buf + option->len);
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Options(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
int index = 0;
|
||||
int count = 0;
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short len = 0;
|
||||
unsigned short optdeltas = 0;
|
||||
|
||||
msg->optcount = 0;
|
||||
while ((count < buflen) && (0xFF != *ptr)) {
|
||||
len = CoAPDeserialize_Option(&msg->options[index], ptr, &optdeltas);
|
||||
msg->optcount += 1;
|
||||
ptr += len;
|
||||
index ++;
|
||||
count += len;
|
||||
}
|
||||
|
||||
return (int)(ptr - buf);
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
if (0xFF == *ptr) {
|
||||
ptr ++;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
msg->payloadlen = buflen - 1;
|
||||
msg->payload = (unsigned char *)ptr;
|
||||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
int count = 0;
|
||||
int remlen = buflen;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
if (NULL == buf || NULL == msg) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (buflen < 4) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
/* Deserialize CoAP header. */
|
||||
count = CoAPDeserialize_Header(msg, ptr);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
/* Deserialize the token, if any. */
|
||||
count = CoAPDeserialize_Token(msg, ptr);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPDeserialize_Options(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
CoAPDeserialize_Payload(msg, ptr, remlen);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "CoAPSerialize.h"
|
||||
#include "CoAPDeserialize.h"
|
||||
#if 0
|
||||
#include "CoAPResource.h"
|
||||
#include "CoAPObserve.h"
|
||||
#include "CoAPInternal.h"
|
||||
#endif
|
||||
#include "CoAPPlatform.h"
|
||||
|
||||
#define COAPAckMsg(header) \
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) \
|
||||
&&(header.type == COAP_MESSAGE_TYPE_ACK))
|
||||
|
||||
#define CoAPRespMsg(header)\
|
||||
((header.code >= 0x40) && (header.code < 0xc0))
|
||||
|
||||
#define CoAPPingMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE)\
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define CoAPResetMsg(header)\
|
||||
(header.type == COAP_MESSAGE_TYPE_RST)
|
||||
|
||||
#define CoAPCONRespMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_205_CONTENT) \
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define CoAPReqMsg(header)\
|
||||
((1 <= header.code) && (32 > header.code))
|
||||
|
||||
|
||||
#define COAP_CUR_VERSION 1
|
||||
#define COAP_WAIT_TIME_MS 2000
|
||||
#define COAP_MAX_MESSAGE_ID 65535
|
||||
#define COAP_MAX_RETRY_COUNT 4
|
||||
#define COAP_ACK_TIMEOUT 2
|
||||
#define COAP_ACK_RANDOM_FACTOR 1
|
||||
#define COAP_MAX_TRANSMISSION_SPAN 10
|
||||
|
||||
int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum, unsigned char *data, unsigned short datalen)
|
||||
{
|
||||
unsigned char *ptr = NULL;
|
||||
if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
message->options[message->optcount].num = optnum - message->optdelta;
|
||||
message->options[message->optcount].len = datalen;
|
||||
ptr = (unsigned char *)coap_malloc(datalen);
|
||||
if (NULL == ptr) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
memset(ptr, 0x00, datalen);
|
||||
memcpy(ptr, data, datalen);
|
||||
message->options[message->optcount].val = ptr;
|
||||
message->optdelta = optnum;
|
||||
message->optcount ++;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum, unsigned char *data, unsigned short *datalen)
|
||||
{
|
||||
unsigned char index = 0;
|
||||
|
||||
for (index = 0; index < message->optcount; index++) {
|
||||
if (message->options[index].num == optnum) {
|
||||
if (*datalen >= message->options[index].len) {
|
||||
memcpy(data, message->options[index].val, message->options[index].len);
|
||||
*datalen = message->options[index].len;
|
||||
return COAP_SUCCESS;
|
||||
} else {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum, unsigned int data)
|
||||
{
|
||||
unsigned char *ptr = NULL;
|
||||
if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
message->options[message->optcount].num = optnum - message->optdelta;
|
||||
|
||||
if (0 == data) {
|
||||
message->options[message->optcount].len = 0;
|
||||
} else if (255 >= data) {
|
||||
message->options[message->optcount].len = 1;
|
||||
ptr = (unsigned char *)coap_malloc(1);
|
||||
if (NULL != ptr) {
|
||||
*ptr = (unsigned char)data;
|
||||
}
|
||||
} else if (65535 >= data) {
|
||||
message->options[message->optcount].len = 2;
|
||||
ptr = (unsigned char *)coap_malloc(2);
|
||||
if (NULL != ptr) {
|
||||
*ptr = (unsigned char)((data & 0xFF00) >> 8);
|
||||
*(ptr + 1) = (unsigned char)(data & 0x00FF);
|
||||
}
|
||||
} else {
|
||||
message->options[message->optcount].len = 4;
|
||||
ptr = (unsigned char *)coap_malloc(4);
|
||||
if (NULL != ptr) {
|
||||
*ptr = (unsigned char)((data & 0xFF000000) >> 24);
|
||||
*(ptr + 1) = (unsigned char)((data & 0x00FF0000) >> 16);
|
||||
*(ptr + 2) = (unsigned char)((data & 0x0000FF00) >> 8);
|
||||
*(ptr + 3) = (unsigned char)(data & 0x000000FF);
|
||||
}
|
||||
}
|
||||
message->options[message->optcount].val = ptr;
|
||||
message->optdelta = optnum;
|
||||
message->optcount += 1;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPUintOption_get(CoAPMessage *message,
|
||||
unsigned short optnum,
|
||||
unsigned int *data)
|
||||
{
|
||||
|
||||
unsigned char index = 0;
|
||||
|
||||
for (index = 0; index < message->optcount; index++) {
|
||||
if (message->options[index].num == optnum) {
|
||||
int byte = 0;
|
||||
switch (message->options[index].len) {
|
||||
case 1:
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
case 2:
|
||||
*data |= (message->options[index].val[byte++] << 8);
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
case 3:
|
||||
*data |= (message->options[index].val[byte++] << 16);
|
||||
*data |= (message->options[index].val[byte++] << 8);
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
case 4:
|
||||
*data |= (message->options[index].val[byte++] << 24);
|
||||
*data |= (message->options[index].val[byte++] << 16);
|
||||
*data |= (message->options[index].val[byte++] << 8);
|
||||
*data |= message->options[index].val[byte++];
|
||||
break;
|
||||
default:
|
||||
*data = 0;
|
||||
break;
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
int CoAPOption_present(CoAPMessage *message, unsigned short option)
|
||||
{
|
||||
unsigned char index = 0;
|
||||
|
||||
|
||||
for (index = 0; index < message->optcount; index++) {
|
||||
if (message->options[index].num == option) {
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->header.msgid = msgid;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageType_set(CoAPMessage *message, unsigned char type)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
if (COAP_MESSAGE_TYPE_CON != type && COAP_MESSAGE_TYPE_NON != type
|
||||
&& COAP_MESSAGE_TYPE_ACK != type && COAP_MESSAGE_TYPE_RST != type) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
message->header.type = type;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->header.code = code;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageCode_get(CoAPMessage *message, CoAPMessageCode *code)
|
||||
{
|
||||
if (NULL == message || NULL == code) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
*code = message->header.code;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
|
||||
unsigned char tokenlen)
|
||||
{
|
||||
if (NULL == message || NULL == token) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
if (COAP_MSG_MAX_TOKEN_LEN < tokenlen) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
memcpy(message->token, token, tokenlen);
|
||||
message->header.tokenlen = tokenlen;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageUserData_set(CoAPMessage *message, void *userdata)
|
||||
{
|
||||
if (NULL == message || NULL == userdata) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->user = userdata;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageKeep_Set(CoAPMessage *message, int keep)
|
||||
{
|
||||
if (NULL == message || keep < 0) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->keep = keep;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
|
||||
unsigned short payloadlen)
|
||||
{
|
||||
if (NULL == message || (0 < payloadlen && NULL == payload)) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->payload = payload;
|
||||
message->payloadlen = payloadlen;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessage_init(CoAPMessage *message)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
memset(message, 0x00, sizeof(CoAPMessage));
|
||||
message->header.version = COAP_CUR_VERSION;
|
||||
message->header.type = COAP_MESSAGE_TYPE_ACK;
|
||||
message->header.tokenlen = 0;
|
||||
message->header.code = COAP_MSG_CODE_EMPTY_MESSAGE;
|
||||
message->header.msgid = 0;
|
||||
message->payload = NULL;
|
||||
message->payloadlen = 0;
|
||||
message->optcount = 0;
|
||||
message->optdelta = 0;
|
||||
message->handler = NULL;
|
||||
message->keep = 0;
|
||||
for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
|
||||
message->options[count].len = 0;
|
||||
message->options[count].num = 0;
|
||||
message->options[count].val = NULL;
|
||||
}
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessage_destory(CoAPMessage *message)
|
||||
{
|
||||
int count = 0;
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
|
||||
if (NULL != message->options[count].val) {
|
||||
coap_free(message->options[count].val);
|
||||
message->options[count].val = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __COAP_PLATFORM_OS_H__
|
||||
#define __COAP_PLATFORM_OS_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define coap_malloc(size) LITE_malloc(size, MEM_MAGIC, "coap.local")
|
||||
#define coap_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define coap_malloc(size) HAL_Malloc(size)
|
||||
#define coap_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#ifdef INFRA_LOG
|
||||
#include "infra_log.h"
|
||||
#define COAP_ERR(...) log_err("coap_local", __VA_ARGS__)
|
||||
#define COAP_WRN(...) log_warning("coap_local", __VA_ARGS__)
|
||||
#define COAP_INFO(...) log_info("coap_local", __VA_ARGS__)
|
||||
#define COAP_TRC(...) log_debug("coap_local", __VA_ARGS__)
|
||||
#define COAP_DUMP(...) log_debug("coap_local", __VA_ARGS__)
|
||||
#define COAP_DEBUG(...) log_debug("coap_local", __VA_ARGS__)
|
||||
#define COAP_FLOW(...) log_flow("coap_local", __VA_ARGS__)
|
||||
#else
|
||||
#define COAP_ERR(...)
|
||||
#define COAP_WRN(...)
|
||||
#define COAP_INFO(...)
|
||||
#define COAP_TRC(...)
|
||||
#define COAP_DUMP(...)
|
||||
#define COAP_DEBUG(...)
|
||||
#define COAP_FLOW(...)
|
||||
#endif
|
||||
|
||||
int platform_is_multicast(const char *ip_str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __COAP_SERIALIZE_H__
|
||||
#define __COAP_SERIALIZE_H__
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg);
|
||||
|
||||
int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "CoAPSerialize.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
int CoAPSerialize_Header(CoAPMessage *msg, unsigned char *buf, unsigned short buflen)
|
||||
{
|
||||
if(4 > buflen){
|
||||
return 0;
|
||||
}
|
||||
buf[0] = (((msg->header.version & 0x3) << 6) | ((msg->header.type & 0x3) << 4))
|
||||
| (msg->header.tokenlen & 0x0F);
|
||||
|
||||
buf[1] = msg->header.code;
|
||||
buf[2] = (msg->header.msgid & 0xFF00) >> 8;
|
||||
buf[3] = (msg->header.msgid & 0x00FF);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int CoAPSerialize_Token(CoAPMessage *msg, unsigned char * buf, unsigned short buflen)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if(buflen < msg->header.tokenlen){
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < msg->header.tokenlen; i++){
|
||||
buf[i] = msg->token[i];
|
||||
}
|
||||
return msg->header.tokenlen;
|
||||
}
|
||||
|
||||
static unsigned short CoAPSerialize_Option(CoAPMsgOption *option, unsigned char *buf)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
if(269 <= option->num){
|
||||
*ptr = ((14 & 0x0F) << 4);
|
||||
}
|
||||
else if(13 <= option->num){
|
||||
*ptr = ((13 & 0x0F) << 4);
|
||||
}
|
||||
else{
|
||||
*ptr = option->num << 4;
|
||||
}
|
||||
|
||||
if (269 <= option->len){
|
||||
*ptr |= (14 & 0x0F);
|
||||
}
|
||||
else if(13 <= option->len){
|
||||
*ptr |= (13 & 0x0F);
|
||||
}
|
||||
else{
|
||||
*ptr |= (option->len & 0x0F);
|
||||
}
|
||||
ptr ++;
|
||||
|
||||
if (269 <= option->num){
|
||||
*ptr = (unsigned char)(((option->num - 269) & 0xFF00) >> 8);
|
||||
*(ptr+1) = (unsigned char)(((option->num - 269) & 0x00FF));
|
||||
ptr += 2;
|
||||
}
|
||||
else if(13 <= option->num){
|
||||
*ptr = (unsigned char)(option->num - 13);
|
||||
ptr ++;
|
||||
}
|
||||
|
||||
|
||||
if (269 <= option->len){
|
||||
*ptr = (unsigned char)(((option->len - 269) & 0xFF00) >> 8);
|
||||
*(ptr+1) = (unsigned char)(((option->len - 269) & 0x00FF));
|
||||
ptr += 2;
|
||||
}
|
||||
else if(13 <= option->len){
|
||||
*ptr = (unsigned char)(option->len - 13);
|
||||
ptr ++;
|
||||
}
|
||||
|
||||
|
||||
memcpy(ptr, option->val, option->len);
|
||||
ptr += option->len;
|
||||
|
||||
return (int)(ptr - buf);
|
||||
}
|
||||
|
||||
unsigned short CoAPSerialize_Options(CoAPMessage *msg, unsigned char * buf, unsigned short buflen)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned short count = 0;
|
||||
|
||||
for (i = 0; i < msg->optcount; i++)
|
||||
{
|
||||
unsigned short len = 0;
|
||||
len = CoAPSerialize_Option(&msg->options[i], &buf[count]);
|
||||
if (0 < len){
|
||||
count += len;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static unsigned short CoAPSerialize_OptionLen(CoAPMsgOption *option)
|
||||
{
|
||||
unsigned short len = 1;
|
||||
|
||||
if(269 <= option->num){
|
||||
len += 2;
|
||||
}
|
||||
else if(13 <= option->num){
|
||||
len += 1;
|
||||
}
|
||||
else{
|
||||
}
|
||||
|
||||
if (269 <= option->len){
|
||||
len += 2;
|
||||
}
|
||||
else if(13 <= option->len){
|
||||
len += 1;
|
||||
}
|
||||
else{
|
||||
}
|
||||
|
||||
len += option->len;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
unsigned short CoAPSerialize_OptionsLen(CoAPMessage *msg)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned short count = 0;
|
||||
|
||||
for (i = 0; i < msg->optcount; i++)
|
||||
{
|
||||
unsigned short len = 0;
|
||||
len = CoAPSerialize_OptionLen(&msg->options[i]);
|
||||
if (0 < len){
|
||||
count += len;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int CoAPSerialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen)
|
||||
{
|
||||
if(msg->payloadlen + 1 > buflen){
|
||||
return 0;
|
||||
}
|
||||
if(msg->payloadlen > 0 && NULL != msg->payload)
|
||||
{
|
||||
*buf = 0xFF;
|
||||
buf ++;
|
||||
memcpy(buf, msg->payload, msg->payloadlen);
|
||||
return msg->payloadlen + 1;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg)
|
||||
{
|
||||
unsigned short msglen = 4;
|
||||
|
||||
msglen += msg->header.tokenlen;
|
||||
msglen += CoAPSerialize_OptionsLen(msg);
|
||||
|
||||
if(0 < msg->payloadlen){
|
||||
msglen += msg->payloadlen;
|
||||
msglen += 1; /*CoAP payload marker*/
|
||||
}
|
||||
|
||||
return msglen;
|
||||
}
|
||||
|
||||
int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
unsigned short count = 0;
|
||||
unsigned short remlen = buflen;
|
||||
|
||||
if(NULL == buf || NULL == msg){
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
count = CoAPSerialize_Header(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPSerialize_Token(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPSerialize_Options(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
count = CoAPSerialize_Payload(msg, ptr, remlen);
|
||||
ptr += count;
|
||||
remlen -= count;
|
||||
|
||||
return (buflen-remlen);
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __IOTX_COAP_API_H__
|
||||
#define __IOTX_COAP_API_H__
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "infra_defs.h"
|
||||
|
||||
/*iotx return code definition*/
|
||||
typedef enum {
|
||||
IOTX_ERR_RECV_MSG_TIMEOUT = -9, /*Receive message timeout */
|
||||
IOTX_ERR_SEND_MSG_FAILED = -8, /* Send message failed*/
|
||||
IOTX_ERR_MSG_TOO_LOOG = -7, /* The payload too loog */
|
||||
IOTX_ERR_URI_TOO_LOOG = -6, /* URI length too long */
|
||||
IOTX_ERR_NOT_AUTHED = -5, /* Client isn't authed */
|
||||
IOTX_ERR_AUTH_FAILED = -4, /* Client authed failed */
|
||||
IOTX_ERR_BUFF_TOO_SHORT = -3, /* Buffer too short */
|
||||
IOTX_ERR_NO_MEM = -2, /* Malloc failed */
|
||||
IOTX_ERR_INVALID_PARAM = -1, /* Invalid parameter */
|
||||
IOTX_SUCCESS = 0, /* Success */
|
||||
} iotx_ret_code_t;
|
||||
|
||||
/* The message payload encode format */
|
||||
typedef enum {
|
||||
IOTX_CONTENT_TYPE_JSON,
|
||||
IOTX_CONTENT_TYPE_CBOR,
|
||||
} iotx_content_type_t;
|
||||
|
||||
/* The message type */
|
||||
typedef enum {
|
||||
IOTX_MESSAGE_CON = 0, /* confirmable message */
|
||||
IOTX_MESSAGE_NON = 1, /* non-confirmable message */
|
||||
IOTX_MESSAGE_ACK = 2, /* acknowledgement message */
|
||||
IOTX_MESSAGE_RST = 3, /* reset message */
|
||||
} iotx_msg_type_t;
|
||||
|
||||
/* IoTx events to notify application */
|
||||
typedef enum {
|
||||
IOTX_COAP_EVENT_SEND_FAILED = 0,
|
||||
IOTX_COAP_EVENT_RECV_FAILED = 1,
|
||||
IOTX_COAP_EVENT_AUTH_FAILED = 2,
|
||||
} iotx_coap_event_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_COAP_RESP_CODE_CONTENT = 0x45, /* Mapping to 2.05, Content*/
|
||||
IOTX_COAP_RESP_CODE_BAD_REQUEST = 0x80, /* Mapping to 4.00, Bad Request*/
|
||||
IOTX_COAP_RESP_CODE_UNAUTHORIZED = 0x81, /* Mapping to 4.01, Token is invalid or expire*/
|
||||
IOTX_COAP_RESP_CODE_NOT_FOUND = 0x84, /* Mapping to 4.04, Path or uri is not found*/
|
||||
IOTX_COAP_RESP_CODE_URL_TOO_LONG = 0x8E, /* Mapping to 4.14, The request url is too long*/
|
||||
IOTX_COAP_RESP_CODE_INTERNAL_SERVER_ERROR = 0xA0,/* Mapping to 5.00, Internal server error*/
|
||||
|
||||
} iotx_coap_resp_code_t;
|
||||
|
||||
/* Callback function to notify the application events.*/
|
||||
typedef void (*iotx_event_handle_t)(void *context, iotx_coap_event_t event, void *p_data);
|
||||
|
||||
/*IoTx device*/
|
||||
typedef struct {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2];
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
|
||||
} iotx_deviceinfo_t;
|
||||
|
||||
typedef struct {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2];
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
|
||||
char module_vendor_id[IOTX_PARTNER_ID_LEN + 1];
|
||||
} iotx_device_info_t;
|
||||
|
||||
/* IoTx initializa parameters */
|
||||
typedef struct {
|
||||
char *p_url; /*Can be NULL*/
|
||||
int wait_time_ms; /*unit is micro second*/
|
||||
iotx_device_info_t *p_devinfo; /*Device info*/
|
||||
iotx_event_handle_t event_handle; /*TODO, not supported now*/
|
||||
} iotx_coap_config_t;
|
||||
|
||||
/* Callback function to handle the response message.*/
|
||||
typedef void (*iotx_response_callback_t)(void *p_arg, void *p_message);
|
||||
|
||||
/* IoTx message definition */
|
||||
typedef struct {
|
||||
unsigned char *p_payload;
|
||||
unsigned short payload_len;
|
||||
iotx_content_type_t content_type;
|
||||
iotx_msg_type_t msg_type;
|
||||
void *user_data;
|
||||
iotx_response_callback_t resp_callback;
|
||||
} iotx_message_t;
|
||||
|
||||
|
||||
/*iotx coap context definition*/
|
||||
typedef void iotx_coap_context_t;
|
||||
|
||||
|
||||
/** @defgroup group_api api
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup group_api_coap coap
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the CoAP client.
|
||||
* This function initialize the data structures and network,
|
||||
* and create the DTLS session.
|
||||
*
|
||||
* @param [in] p_config: Specify the CoAP client parameter.
|
||||
*
|
||||
* @retval NULL : Initialize failed.
|
||||
* @retval NOT_NULL : The contex of CoAP client.
|
||||
* @see None.
|
||||
*/
|
||||
iotx_coap_context_t *IOT_CoAP_Init(iotx_coap_config_t *p_config);
|
||||
|
||||
/**
|
||||
* @brief De-initialize the CoAP client.
|
||||
* This function release CoAP DTLS session.
|
||||
* and release the related resource.
|
||||
*
|
||||
* @param [in] p_context: Pointer of contex, specify the CoAP client.
|
||||
*
|
||||
* @return None.
|
||||
* @see None.
|
||||
*/
|
||||
DLL_IOT_API void IOT_CoAP_Deinit(iotx_coap_context_t **p_context);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle device name authentication with remote server.
|
||||
*
|
||||
* @param [in] p_context: Pointer of contex, specify the CoAP client.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : Authenticate success.
|
||||
* @retval IOTX_ERR_SEND_MSG_FAILED : Send authentication message failed.
|
||||
* @retval IOTX_ERR_AUTH_FAILED : Authenticate failed or timeout.
|
||||
* @see iotx_ret_code_t.
|
||||
*/
|
||||
DLL_IOT_API int IOT_CoAP_DeviceNameAuth(iotx_coap_context_t *p_context);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle CoAP response packet from remote server,
|
||||
* and process timeout request etc..
|
||||
*
|
||||
* @param [in] p_context : Pointer of contex, specify the CoAP client.
|
||||
*
|
||||
* @return status.
|
||||
* @see iotx_ret_code_t.
|
||||
*/
|
||||
DLL_IOT_API int IOT_CoAP_Yield(iotx_coap_context_t *p_context);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a message with specific path to server.
|
||||
* Client must authentication with server before send message.
|
||||
*
|
||||
* @param [in] p_context : Pointer of contex, specify the CoAP client.
|
||||
* @param [in] p_path: Specify the path name.
|
||||
* @param [in] p_message: Message to be sent.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : Send the message success.
|
||||
* @retval IOTX_ERR_MSG_TOO_LOOG : The message length is too long.
|
||||
* @retval IOTX_ERR_NOT_AUTHED : The client hasn't authenticated with server
|
||||
* @see iotx_ret_code_t.
|
||||
*/
|
||||
DLL_IOT_API int IOT_CoAP_SendMessage(iotx_coap_context_t *p_context, char *p_path, iotx_message_t *p_message);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the length and payload pointer of specified message.
|
||||
*
|
||||
* @param [in] p_message: Pointer to the message to get the payload. Should not be NULL.
|
||||
* @param [out] pp_payload: Pointer to the payload.
|
||||
* @param [out] p_len: Size of the payload.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : Get the payload success.
|
||||
* @retval IOTX_ERR_INVALID_PARAM : Can't get the payload due to invalid parameter.
|
||||
* @see iotx_ret_code_t.
|
||||
**/
|
||||
DLL_IOT_API int IOT_CoAP_GetMessagePayload(void *p_message, unsigned char **pp_payload, int *p_len);
|
||||
|
||||
/**
|
||||
* @brief Get the response code from a CoAP message.
|
||||
*
|
||||
* @param [in] p_message: Pointer to the message to add the address information to.
|
||||
* Should not be NULL.
|
||||
* @param [out] p_resp_code: The response code.
|
||||
*
|
||||
* @retval IOTX_SUCCESS : When get the response code to message success.
|
||||
* @retval IOTX_ERR_INVALID_PARAM : Pointer to the message is NULL.
|
||||
* @see iotx_ret_code_t.
|
||||
**/
|
||||
DLL_IOT_API int IOT_CoAP_GetMessageCode(void *p_message, iotx_coap_resp_code_t *p_resp_code);
|
||||
|
||||
/** @} */ /* end of api_coap */
|
||||
/** @} */ /* end of api */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef _COAP_WRAPPER_H_
|
||||
#define _COAP_WRAPPER_H_
|
||||
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_compat.h"
|
||||
#include "wrappers_defs.h"
|
||||
|
||||
void *HAL_Malloc(uint32_t size);
|
||||
void HAL_Free(void *ptr);
|
||||
void HAL_SleepMs(uint32_t ms);
|
||||
uint64_t HAL_UptimeMs(void);
|
||||
void HAL_Srandom(uint32_t seed);
|
||||
uint32_t HAL_Random(uint32_t region);
|
||||
void HAL_Printf(const char *fmt, ...);
|
||||
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
|
||||
|
||||
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
|
||||
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
|
||||
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
|
||||
|
||||
int HAL_SetProductKey(char *product_key);
|
||||
int HAL_SetProductSecret(char *product_secret);
|
||||
int HAL_SetDeviceName(char *device_name);
|
||||
int HAL_SetDeviceSecret(char *device_secret);
|
||||
|
||||
DLL_HAL_API int HAL_DTLSHooks_set(dtls_hooks_t *hooks);
|
||||
DLL_HAL_API DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options);
|
||||
DLL_HAL_API unsigned int HAL_DTLSSession_write(DTLSContext *context,
|
||||
const unsigned char *p_data,
|
||||
unsigned int *p_datalen);
|
||||
DLL_HAL_API unsigned int HAL_DTLSSession_read(DTLSContext *context,
|
||||
unsigned char *p_data,
|
||||
unsigned int *p_datalen,
|
||||
unsigned int timeout_ms);
|
||||
DLL_HAL_API unsigned int HAL_DTLSSession_free(DTLSContext *context);
|
||||
intptr_t HAL_UDP_create(char *host, unsigned short port);
|
||||
intptr_t HAL_UDP_create_without_connect(const char *host, unsigned short port);
|
||||
int HAL_UDP_write(intptr_t p_socket,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen);
|
||||
int HAL_UDP_readTimeout(intptr_t p_socket,
|
||||
unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout);
|
||||
int HAL_UDP_close_without_connect(intptr_t sockfd);
|
||||
int HAL_UDP_recvfrom(intptr_t sockfd,
|
||||
NetworkAddr *p_remote,
|
||||
unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout_ms);
|
||||
int HAL_UDP_sendto(intptr_t sockfd,
|
||||
const NetworkAddr *p_remote,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout_ms);
|
||||
int HAL_UDP_joinmulticast(intptr_t sockfd,
|
||||
char *p_group);
|
||||
uint32_t HAL_Wifi_Get_IP(char ip_str[NETWORK_ADDR_LEN], const char *ifname);
|
||||
p_HAL_Aes128_t HAL_Aes128_Init(
|
||||
const uint8_t *key,
|
||||
const uint8_t *iv,
|
||||
AES_DIR_t dir);
|
||||
int HAL_Aes128_Destroy(p_HAL_Aes128_t aes);
|
||||
int HAL_Aes128_Cbc_Encrypt(
|
||||
p_HAL_Aes128_t aes,
|
||||
const void *src,
|
||||
size_t blockNum,
|
||||
void *dst);
|
||||
int HAL_Aes128_Cbc_Decrypt(
|
||||
p_HAL_Aes128_t aes,
|
||||
const void *src,
|
||||
size_t blockNum,
|
||||
void *dst);
|
||||
void *HAL_MutexCreate(void);
|
||||
void HAL_MutexDestroy(void *mutex);
|
||||
void HAL_MutexLock(void *mutex);
|
||||
void HAL_MutexUnlock(void *mutex);
|
||||
void *HAL_SemaphoreCreate(void);
|
||||
void HAL_SemaphoreDestroy(void *sem);
|
||||
int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
|
||||
void HAL_SemaphorePost(void *sem);
|
||||
int HAL_ThreadCreate(
|
||||
void **thread_handle,
|
||||
void *(*work_routine)(void *),
|
||||
void *arg,
|
||||
hal_os_thread_param_t *hal_os_thread_param,
|
||||
int *stack_used);
|
||||
void HAL_ThreadDelete(void *thread_handle);
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "CoAPServer.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef __IOTX_COAP_CONFIG__
|
||||
#define __IOTX_COAP_CONFIG__
|
||||
|
||||
#define COAP_MSG_MAX_TOKEN_LEN 8
|
||||
#define COAP_MSG_MAX_OPTION_NUM 12
|
||||
#define COAP_MSG_MAX_PATH_LEN 128
|
||||
#ifndef COAP_LARGE_MEMORY_SUPPORT
|
||||
#define COAP_MSG_MAX_PDU_LEN 1280
|
||||
#else
|
||||
#define COAP_MSG_MAX_PDU_LEN 4096
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_COAP_AUTH_TIMEOUT
|
||||
#define CONFIG_COAP_AUTH_TIMEOUT (3 * 1000)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __IOTX_COAP_INTERNAL__
|
||||
#define __IOTX_COAP_INTERNAL__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "infra_string.h"
|
||||
#include "infra_compat.h"
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_log.h"
|
||||
#include "infra_json_parser.h"
|
||||
#include "infra_cjson.h"
|
||||
#include "infra_list.h"
|
||||
#include "infra_md5.h"
|
||||
#include "infra_sha256.h"
|
||||
#include "infra_report.h"
|
||||
#include "iotx_coap_config.h"
|
||||
#include "coap_wrapper.h"
|
||||
#include "iotx_coap_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*CoAP Content Type*/
|
||||
#define COAP_CT_TEXT_PLAIN 0 /* text/plain (UTF-8) */
|
||||
#define COAP_CT_APP_LINK_FORMAT 40 /* application/link-format */
|
||||
#define COAP_CT_APP_XML 41 /* application/xml */
|
||||
#define COAP_CT_APP_OCTET_STREAM 42 /* application/octet-stream */
|
||||
#define COAP_CT_APP_RDF_XML 43 /* application/rdf+xml */
|
||||
#define COAP_CT_APP_EXI 47 /* application/exi */
|
||||
#define COAP_CT_APP_JSON 50 /* application/json */
|
||||
#define COAP_CT_APP_CBOR 60 /* application/cbor */
|
||||
|
||||
/*CoAP option types. */
|
||||
#define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */
|
||||
#define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */
|
||||
#define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */
|
||||
#define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */
|
||||
#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none)*/
|
||||
#define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */
|
||||
#define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */
|
||||
#define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */
|
||||
#define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */
|
||||
#define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */
|
||||
#define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */
|
||||
#define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */
|
||||
#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */
|
||||
#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */
|
||||
#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */
|
||||
#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1024 B, (none) */
|
||||
#define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */
|
||||
#define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */
|
||||
#define COAP_OPTION_AUTH_TOKEN 61 /* C, String, 1-255B, (none)*/
|
||||
|
||||
#define COAP_PERM_NONE 0x0000
|
||||
#define COAP_PERM_GET 0x0001
|
||||
#define COAP_PERM_POST 0x0002
|
||||
#define COAP_PERM_PUT 0x0004
|
||||
#define COAP_PERM_DELETE 0x0008
|
||||
#define COAP_PERM_OBSERVE 0x0100
|
||||
|
||||
/*CoAP Message types*/
|
||||
#define COAP_MESSAGE_TYPE_CON 0
|
||||
#define COAP_MESSAGE_TYPE_NON 1
|
||||
#define COAP_MESSAGE_TYPE_ACK 2
|
||||
#define COAP_MESSAGE_TYPE_RST 3
|
||||
|
||||
/* CoAP module error code base */
|
||||
#define COAP_ERROR_BASE (1<<8)
|
||||
#define COAP_ERROR_DTLS_BASE (1<<16)
|
||||
|
||||
/* CoAP base error code */
|
||||
#define COAP_SUCCESS (0) /* Successful */
|
||||
#define COAP_ERROR_INVALID_PARAM (COAP_ERROR_BASE | 1) /* Invalid Parameter */
|
||||
#define COAP_ERROR_NULL (COAP_ERROR_BASE | 2) /* Null Pointer */
|
||||
#define COAP_ERROR_MALLOC (COAP_ERROR_BASE | 3)
|
||||
#define COAP_ERROR_INVALID_LENGTH (COAP_ERROR_BASE | 4) /* Invalid Length */
|
||||
#define COAP_ERROR_DATA_SIZE (COAP_ERROR_BASE | 5) /* Data size exceeds limit */
|
||||
#define COAP_ERROR_INVALID_URI (COAP_ERROR_BASE | 6)
|
||||
#define COAP_ERROR_NOT_FOUND (COAP_ERROR_BASE | 7)
|
||||
#define COAP_ERROR_NET_INIT_FAILED (COAP_ERROR_BASE | 8)
|
||||
#define COAP_ERROR_INTERNAL (COAP_ERROR_BASE | 9) /* Internal Error */
|
||||
#define COAP_ERROR_WRITE_FAILED (COAP_ERROR_BASE | 10)
|
||||
#define COAP_ERROR_READ_FAILED (COAP_ERROR_BASE | 11)
|
||||
#define COAP_ERROR_ENCRYPT_FAILED (COAP_ERROR_BASE | 12)
|
||||
#define COAP_ERROR_UNSUPPORTED (COAP_ERROR_BASE | 13)
|
||||
#define COAP_ERROR_OBJ_ALREADY_EXIST (COAP_ERROR_BASE | 14)
|
||||
|
||||
#define COAP_MSG_CODE_DEF(N) (((N)/100 << 5) | (N)%100)
|
||||
|
||||
/*CoAP Message codes*/
|
||||
typedef enum {
|
||||
/* CoAP Empty Message */
|
||||
COAP_MSG_CODE_EMPTY_MESSAGE = COAP_MSG_CODE_DEF(0), /* Mapping to CoAP code 0.00 */
|
||||
|
||||
/* CoAP Method Codes */
|
||||
COAP_MSG_CODE_GET = COAP_MSG_CODE_DEF(1), /* CoAP Get method */
|
||||
COAP_MSG_CODE_POST = COAP_MSG_CODE_DEF(2), /* CoAP Post method */
|
||||
COAP_MSG_CODE_PUT = COAP_MSG_CODE_DEF(3), /* CoAP Put method */
|
||||
COAP_MSG_CODE_DELETE = COAP_MSG_CODE_DEF(4), /* CoAP Delete method */
|
||||
|
||||
/* CoAP Success Response Codes */
|
||||
COAP_MSG_CODE_201_CREATED = COAP_MSG_CODE_DEF(201), /* Mapping to CoAP code 2.01, Hex:0x41, Created */
|
||||
COAP_MSG_CODE_202_DELETED = COAP_MSG_CODE_DEF(202), /* Mapping to CoAP code 2.02, Hex:0x42, Deleted*/
|
||||
COAP_MSG_CODE_203_VALID = COAP_MSG_CODE_DEF(203), /* Mapping to CoAP code 2.03, Hex:0x43, Valid*/
|
||||
COAP_MSG_CODE_204_CHANGED = COAP_MSG_CODE_DEF(204), /* Mapping to CoAP code 2.04, Hex:0x44, Changed*/
|
||||
COAP_MSG_CODE_205_CONTENT = COAP_MSG_CODE_DEF(205), /* Mapping to CoAP code 2.05, Hex:0x45, Content*/
|
||||
COAP_MSG_CODE_231_CONTINUE = COAP_MSG_CODE_DEF(231), /* Mapping to CoAP code 2.31, Hex:0x5F, Continue*/
|
||||
|
||||
/* CoAP Client Error Response Codes */
|
||||
COAP_MSG_CODE_400_BAD_REQUEST = COAP_MSG_CODE_DEF(400), /* Mapping to CoAP code 4.00, Hex:0x80, Bad Request */
|
||||
COAP_MSG_CODE_401_UNAUTHORIZED = COAP_MSG_CODE_DEF(401), /* Mapping to CoAP code 4.01, Hex:0x81, Unauthorized */
|
||||
COAP_MSG_CODE_402_BAD_OPTION = COAP_MSG_CODE_DEF(402), /* Mapping to CoAP code 4.02, Hex:0x82, Bad Option */
|
||||
COAP_MSG_CODE_403_FORBIDDEN = COAP_MSG_CODE_DEF(403), /* Mapping to CoAP code 4.03, Hex:0x83, Forbidden */
|
||||
COAP_MSG_CODE_404_NOT_FOUND = COAP_MSG_CODE_DEF(404), /* Mapping to CoAP code 4.04, Hex:0x84, Not Found */
|
||||
COAP_MSG_CODE_405_METHOD_NOT_ALLOWED = COAP_MSG_CODE_DEF(405), /* Mapping to CoAP code 4.05, Hex:0x85, Method Not Allowed */
|
||||
COAP_MSG_CODE_406_NOT_ACCEPTABLE = COAP_MSG_CODE_DEF(406), /* Mapping to CoAP code 4.06, Hex:0x86, Not Acceptable */
|
||||
COAP_MSG_CODE_408_REQUEST_ENTITY_INCOMPLETE = COAP_MSG_CODE_DEF(408), /* Mapping to CoAP code 4.08, Hex:0x88, Request Entity Incomplete */
|
||||
COAP_MSG_CODE_412_PRECONDITION_FAILED = COAP_MSG_CODE_DEF(412), /* Mapping to CoAP code 4.12, Hex:0x8C, Precondition Failed */
|
||||
COAP_MSG_CODE_413_REQUEST_ENTITY_TOO_LARGE = COAP_MSG_CODE_DEF(413), /* Mapping to CoAP code 4.13, Hex:0x8D, Request Entity Too Large */
|
||||
COAP_MSG_CODE_415_UNSUPPORTED_CONTENT_FORMAT = COAP_MSG_CODE_DEF(415), /* Mapping to CoAP code 4.15, Hex:0x8F, Unsupported Content-Format */
|
||||
|
||||
/* CoAP Server Error Response Codes */
|
||||
COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR = COAP_MSG_CODE_DEF(500), /* Mapping to CoAP code 5.00, Hex:0xA0, Internal Server Error */
|
||||
COAP_MSG_CODE_501_NOT_IMPLEMENTED = COAP_MSG_CODE_DEF(501), /* Mapping to CoAP code 5.01, Hex:0xA1, Not Implemented */
|
||||
COAP_MSG_CODE_502_BAD_GATEWAY = COAP_MSG_CODE_DEF(502), /* Mapping to CoAP code 5.02, Hex:0xA2, Bad Gateway */
|
||||
COAP_MSG_CODE_503_SERVICE_UNAVAILABLE = COAP_MSG_CODE_DEF(503), /* Mapping to CoAP code 5.03, Hex:0xA3, Service Unavailable */
|
||||
COAP_MSG_CODE_504_GATEWAY_TIMEOUT = COAP_MSG_CODE_DEF(504), /* Mapping to CoAP code 5.04, Hex:0xA4, Gateway Timeout */
|
||||
COAP_MSG_CODE_505_PROXYING_NOT_SUPPORTED = COAP_MSG_CODE_DEF(505) /* Mapping to CoAP code 5.05, Hex:0xA5, Proxying Not Supported */
|
||||
|
||||
} CoAPMessageCode;
|
||||
|
||||
typedef enum {
|
||||
COAP_REQUEST_SUCCESS = 0,
|
||||
COAP_RECV_RESP_TIMEOUT,
|
||||
COAP_RECV_RESP_SUC,
|
||||
} CoAPReqResult;
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
unsigned char *data;
|
||||
} CoAPLenString;
|
||||
|
||||
typedef struct {
|
||||
unsigned char version : 2;
|
||||
unsigned char type : 2;
|
||||
unsigned char tokenlen : 4;
|
||||
unsigned char code;
|
||||
unsigned short msgid;
|
||||
} CoAPMsgHeader;
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned short num;
|
||||
unsigned short len;
|
||||
unsigned char *val;
|
||||
} CoAPMsgOption;
|
||||
|
||||
typedef void CoAPContext;
|
||||
typedef struct CoAPMessage CoAPMessage;
|
||||
|
||||
typedef void (*CoAPSendMsgHandler)(CoAPContext *context, CoAPReqResult result, void *userdata, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
|
||||
typedef void (*CoAPEventNotifier)(unsigned int event, NetworkAddr *remote, void *message);
|
||||
|
||||
typedef void (*CoAPRecvMsgHandler)(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *message);
|
||||
|
||||
typedef int (*CoAPDataEncrypt)(CoAPContext *context, const char *paths, NetworkAddr *addr, CoAPMessage *message,
|
||||
CoAPLenString *src, CoAPLenString *dest);
|
||||
typedef void (*CoAPRespMsgHandler)(void *data, void *message);
|
||||
|
||||
struct CoAPMessage {
|
||||
CoAPMsgHeader header;
|
||||
unsigned char token[COAP_MSG_MAX_TOKEN_LEN];
|
||||
CoAPMsgOption options[COAP_MSG_MAX_OPTION_NUM];
|
||||
unsigned char optcount;
|
||||
unsigned char optdelta;
|
||||
unsigned short payloadlen;
|
||||
unsigned char *payload;
|
||||
CoAPSendMsgHandler handler;
|
||||
CoAPRespMsgHandler resp;
|
||||
void *user;
|
||||
int keep;
|
||||
};
|
||||
|
||||
|
||||
/* CoAP message options APIs*/
|
||||
extern int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short datalen);
|
||||
|
||||
extern int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short *datalen);
|
||||
|
||||
extern int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned int data);
|
||||
|
||||
extern int CoAPUintOption_get(CoAPMessage *message,
|
||||
unsigned short optnum,
|
||||
unsigned int *data);
|
||||
|
||||
extern int CoAPOption_present(CoAPMessage *message, unsigned short option);
|
||||
|
||||
|
||||
|
||||
extern int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid);
|
||||
|
||||
extern int CoAPMessageType_set(CoAPMessage *message, unsigned char type);
|
||||
|
||||
extern int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code);
|
||||
|
||||
extern int CoAPMessageCode_get(CoAPMessage *message, CoAPMessageCode *code);
|
||||
|
||||
extern int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
|
||||
unsigned char tokenlen);
|
||||
|
||||
extern int CoAPMessageUserData_set(CoAPMessage *message, void *userdata);
|
||||
|
||||
extern int CoAPMessageKeep_Set(CoAPMessage *message, int keep);
|
||||
|
||||
extern int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
|
||||
unsigned short payloadlen);
|
||||
|
||||
extern int CoAPMessageHandler_set(CoAPMessage *message, CoAPSendMsgHandler handler);
|
||||
|
||||
extern int CoAPMessage_init(CoAPMessage *message);
|
||||
|
||||
extern int CoAPMessage_destory(CoAPMessage *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ctype.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPInternal.h"
|
||||
#include "CoAPNetwork.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPObserve.h"
|
||||
|
||||
#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */
|
||||
#define COAPS_DEFAULT_PORT 5684 /* CoAP default UDP port for secure transmission */
|
||||
#define COAP_DEFAULT_SENDLIST_MAXCOUNT 8
|
||||
#define COAP_DEFAULT_RES_MAXCOUNT 8
|
||||
#define COAP_DEFAULT_OBS_MAXCOUNT 8
|
||||
|
||||
#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */
|
||||
#define COAP_DEFAULT_HOST_LEN 128
|
||||
#define COAP_DEFAULT_WAIT_TIME_MS 2000
|
||||
|
||||
|
||||
CoAPContext *CoAPContext_create(CoAPInitParam *param)
|
||||
{
|
||||
CoAPIntContext *p_ctx = NULL;
|
||||
NetworkInit network_param;
|
||||
|
||||
memset(&network_param, 0x00, sizeof(NetworkInit));
|
||||
p_ctx = coap_malloc(sizeof(CoAPIntContext));
|
||||
if (NULL == p_ctx) {
|
||||
COAP_ERR("malloc for coap context failed");
|
||||
goto err;
|
||||
}
|
||||
COAP_DEBUG("Send List Max-Count: %d", param->send_maxcount);
|
||||
COAP_DEBUG("Observe Server Max-Count: %d", param->obs_maxcount);
|
||||
COAP_DEBUG("Observe Client Max-Count: %d", param->obs_maxcount);
|
||||
COAP_DEBUG("Resource Max-Count: %d", param->res_maxcount);
|
||||
COAP_DEBUG("MultiCast Address: %s:%d", param->group, param->port);
|
||||
COAP_DEBUG("Send/Recv Wait time: %dms", param->waittime);
|
||||
|
||||
memset(p_ctx, 0, sizeof(CoAPIntContext));
|
||||
p_ctx->message_id = 1;
|
||||
p_ctx->notifier = param->notifier;
|
||||
p_ctx->appdata = param->appdata;
|
||||
|
||||
#ifdef USE_SENDBUFF
|
||||
p_ctx->sendbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
|
||||
if (NULL == p_ctx->sendbuf) {
|
||||
COAP_ERR("not enough memory");
|
||||
goto err;
|
||||
}
|
||||
memset(p_ctx->sendbuf, 0x00, COAP_MSG_MAX_PDU_LEN);
|
||||
#endif
|
||||
|
||||
p_ctx->recvbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
|
||||
if (NULL == p_ctx->recvbuf) {
|
||||
COAP_ERR("not enough memory");
|
||||
goto err;
|
||||
}
|
||||
memset(p_ctx->recvbuf, 0x00, COAP_MSG_MAX_PDU_LEN);
|
||||
|
||||
if (0 == param->waittime) {
|
||||
p_ctx->waittime = COAP_DEFAULT_WAIT_TIME_MS;
|
||||
} else {
|
||||
p_ctx->waittime = param->waittime;
|
||||
}
|
||||
p_ctx->mutex = HAL_MutexCreate();
|
||||
if (NULL == p_ctx->mutex) {
|
||||
COAP_ERR("Mutex Create failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*Init message send list mutex*/
|
||||
p_ctx->sendlist.list_mutex = HAL_MutexCreate();
|
||||
HAL_MutexLock(p_ctx->sendlist.list_mutex);
|
||||
/*CoAP message send list*/
|
||||
INIT_LIST_HEAD(&p_ctx->sendlist.list);
|
||||
p_ctx->sendlist.count = 0;
|
||||
HAL_MutexUnlock(p_ctx->sendlist.list_mutex);
|
||||
|
||||
if (0 != param->send_maxcount) {
|
||||
p_ctx->sendlist.maxcount = param->send_maxcount;
|
||||
} else {
|
||||
p_ctx->sendlist.maxcount = COAP_DEFAULT_SENDLIST_MAXCOUNT;
|
||||
}
|
||||
|
||||
if (0 == param->res_maxcount) {
|
||||
param->res_maxcount = COAP_DEFAULT_RES_MAXCOUNT;
|
||||
}
|
||||
CoAPResource_init(p_ctx, param->res_maxcount);
|
||||
|
||||
#ifndef COAP_OBSERVE_SERVER_DISABLE
|
||||
if (0 == param->obs_maxcount) {
|
||||
param->obs_maxcount = COAP_DEFAULT_OBS_MAXCOUNT;
|
||||
}
|
||||
CoAPObsServer_init(p_ctx, param->obs_maxcount);
|
||||
#endif
|
||||
|
||||
#ifndef COAP_OBSERVE_CLIENT_DISABLE
|
||||
if (0 == param->obs_maxcount) {
|
||||
param->obs_maxcount = COAP_DEFAULT_OBS_MAXCOUNT;
|
||||
}
|
||||
CoAPObsClient_init(p_ctx, param->obs_maxcount);
|
||||
#endif
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
network_param.type = COAP_NETWORK_DTLS;
|
||||
network_param.port = COAPS_DEFAULT_PORT;
|
||||
#else
|
||||
network_param.type = COAP_NETWORK_NOSEC;
|
||||
network_param.port = param->port;
|
||||
network_param.group = param->group;
|
||||
#endif
|
||||
|
||||
|
||||
/*CoAP network init*/
|
||||
p_ctx->p_network = CoAPNetwork_init(&network_param);
|
||||
|
||||
if (NULL == p_ctx->p_network) {
|
||||
COAP_ERR("CoAP Network init failed, exit");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return p_ctx;
|
||||
err:
|
||||
if (NULL == p_ctx) {
|
||||
return p_ctx;
|
||||
}
|
||||
|
||||
if (NULL != p_ctx->recvbuf) {
|
||||
coap_free(p_ctx->recvbuf);
|
||||
p_ctx->recvbuf = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_SENDBUFF
|
||||
if (NULL != p_ctx->sendbuf) {
|
||||
coap_free(p_ctx->sendbuf);
|
||||
p_ctx->sendbuf = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef COAP_OBSERVE_SERVER_DISABLE
|
||||
CoAPObsServer_deinit(p_ctx);
|
||||
#endif
|
||||
|
||||
#ifndef COAP_OBSERVE_CLIENT_DISABLE
|
||||
CoAPObsClient_deinit(p_ctx);
|
||||
#endif
|
||||
|
||||
CoAPResource_deinit(p_ctx);
|
||||
|
||||
if (NULL != p_ctx->sendlist.list_mutex) {
|
||||
HAL_MutexDestroy(p_ctx->sendlist.list_mutex);
|
||||
p_ctx->sendlist.list_mutex = NULL;
|
||||
}
|
||||
|
||||
if (NULL != p_ctx->mutex) {
|
||||
HAL_MutexDestroy(p_ctx->mutex);
|
||||
p_ctx->mutex = NULL;
|
||||
}
|
||||
|
||||
coap_free(p_ctx);
|
||||
p_ctx = NULL;
|
||||
|
||||
/* TODO: release the resource */
|
||||
return (CoAPContext *)p_ctx;
|
||||
}
|
||||
|
||||
void *CoAPContextAppdata_get(CoAPContext *context)
|
||||
{
|
||||
CoAPIntContext *p_ctx = (CoAPIntContext *)context;
|
||||
if (NULL == p_ctx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)p_ctx->appdata;
|
||||
}
|
||||
|
||||
|
||||
void CoAPContext_free(CoAPContext *context)
|
||||
{
|
||||
CoAPIntContext *p_ctx = NULL;
|
||||
CoAPSendNode *cur = NULL, *next = NULL;
|
||||
if (NULL == context) {
|
||||
return;
|
||||
}
|
||||
|
||||
p_ctx = (CoAPIntContext *)context;
|
||||
|
||||
CoAPNetwork_deinit(p_ctx->p_network);
|
||||
COAP_DEBUG("CoAP Network Deinit");
|
||||
|
||||
HAL_MutexLock(p_ctx->sendlist.list_mutex);
|
||||
list_for_each_entry_safe(cur, next, &p_ctx->sendlist.list, sendlist, CoAPSendNode) {
|
||||
if (NULL != cur) {
|
||||
if (NULL != cur->message) {
|
||||
coap_free(cur->message);
|
||||
cur->message = NULL;
|
||||
}
|
||||
coap_free(cur);
|
||||
cur = NULL;
|
||||
}
|
||||
}
|
||||
INIT_LIST_HEAD(&p_ctx->sendlist.list);
|
||||
HAL_MutexUnlock(p_ctx->sendlist.list_mutex);
|
||||
HAL_MutexDestroy(p_ctx->sendlist.list_mutex);
|
||||
p_ctx->sendlist.list_mutex = NULL;
|
||||
HAL_MutexDestroy(p_ctx->mutex);
|
||||
p_ctx->mutex = NULL;
|
||||
COAP_DEBUG("Release Send List and Memory");
|
||||
|
||||
#ifndef COAP_OBSERVE_SERVER_DISABLE
|
||||
CoAPObsServer_deinit(p_ctx);
|
||||
COAP_DEBUG("CoAP Observe Server Deinit");
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef COAP_OBSERVE_CLIENT_DISABLE
|
||||
CoAPObsClient_deinit(p_ctx);
|
||||
COAP_DEBUG("CoAP Observe Client Deinit");
|
||||
#endif
|
||||
|
||||
CoAPResource_deinit(p_ctx);
|
||||
COAP_DEBUG("CoAP Resource unregister");
|
||||
|
||||
if (NULL != p_ctx->recvbuf) {
|
||||
coap_free(p_ctx->recvbuf);
|
||||
p_ctx->recvbuf = NULL;
|
||||
COAP_DEBUG("Release The Recv Memory");
|
||||
}
|
||||
#ifdef USE_SENDBUFF
|
||||
if (NULL != p_ctx->sendbuf) {
|
||||
coap_free(p_ctx->sendbuf);
|
||||
p_ctx->sendbuf = NULL;
|
||||
COAP_DEBUG("Release The Send Memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NULL != p_ctx) {
|
||||
coap_free(p_ctx);
|
||||
p_ctx = NULL;
|
||||
COAP_DEBUG("Release The CoAP Context");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __COAP_EXPORT_H__
|
||||
#define __COAP_EXPORT_H__
|
||||
|
||||
#include "../iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct {
|
||||
unsigned char send_maxcount; /*list maximal count*/
|
||||
unsigned char obs_maxcount; /*observe maximal count*/
|
||||
unsigned short port; /* Local port */
|
||||
char *group; /* Multicast address */
|
||||
unsigned int waittime;
|
||||
CoAPEventNotifier notifier;
|
||||
void *appdata;
|
||||
unsigned char res_maxcount;
|
||||
} CoAPInitParam;
|
||||
|
||||
typedef enum {
|
||||
PATH_NORMAL,
|
||||
PATH_FILTER,
|
||||
} path_type_t;
|
||||
|
||||
CoAPContext *CoAPContext_create(CoAPInitParam *param);
|
||||
|
||||
void CoAPContext_free(CoAPContext *context);
|
||||
|
||||
void *CoAPContextAppdata_get(CoAPContext *context);
|
||||
|
||||
/* CoAP message options APIs*/
|
||||
extern int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short datalen);
|
||||
|
||||
extern int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short *datalen);
|
||||
|
||||
extern int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned int data);
|
||||
|
||||
extern int CoAPUintOption_get(CoAPMessage *message,
|
||||
unsigned short optnum,
|
||||
unsigned int *data);
|
||||
|
||||
extern int CoAPOption_present(CoAPMessage *message, unsigned short option);
|
||||
|
||||
|
||||
/*CoAP Message APIs*/
|
||||
extern unsigned short CoAPMessageId_gen(CoAPContext *context);
|
||||
|
||||
extern int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid);
|
||||
|
||||
extern int CoAPMessageType_set(CoAPMessage *message, unsigned char type);
|
||||
|
||||
extern int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code);
|
||||
|
||||
extern int CoAPMessageCode_get(CoAPMessage *message, CoAPMessageCode *code);
|
||||
|
||||
extern int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
|
||||
unsigned char tokenlen);
|
||||
|
||||
extern int CoAPMessageUserData_set(CoAPMessage *message, void *userdata);
|
||||
|
||||
extern int CoAPMessageKeep_Set(CoAPMessage *message, int keep);
|
||||
|
||||
extern int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
|
||||
unsigned short payloadlen);
|
||||
|
||||
extern int CoAPMessageHandler_set(CoAPMessage *message, CoAPSendMsgHandler handler);
|
||||
|
||||
extern int CoAPMessage_init(CoAPMessage *message);
|
||||
|
||||
extern int CoAPMessage_destory(CoAPMessage *message);
|
||||
|
||||
extern int CoAPMessage_send(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message);
|
||||
|
||||
extern int CoAPMessage_process(CoAPContext *context, unsigned int timeout);
|
||||
|
||||
extern int CoAPMessage_retransmit(CoAPContext *context);
|
||||
|
||||
extern int CoAPMessage_cycle(CoAPContext *context);
|
||||
|
||||
extern int CoAPMessage_cancel(CoAPContext *context, CoAPMessage *message);
|
||||
|
||||
extern int CoAPMessageId_cancel(CoAPContext *context, unsigned short msgid);
|
||||
|
||||
extern void CoAPMessage_dump(NetworkAddr *remote, CoAPMessage *message);
|
||||
/*CoAP Resource APIs*/
|
||||
extern int CoAPResource_register(CoAPContext *context, const char *path,
|
||||
unsigned short permission, unsigned int ctype,
|
||||
unsigned int maxage, CoAPRecvMsgHandler callback);
|
||||
|
||||
/*CoAP observe APIs*/
|
||||
extern int CoAPObsServer_add(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *request);
|
||||
|
||||
extern int CoAPObsServer_notify(CoAPContext *context,
|
||||
const char *path, unsigned char *payload,
|
||||
unsigned short payloadlen, CoAPDataEncrypt handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __COAP_INTERNAL_H__
|
||||
#define __COAP_INTERNAL_H__
|
||||
#include "CoAPNetwork.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *list_mutex;
|
||||
struct list_head list;
|
||||
unsigned char count;
|
||||
unsigned char maxcount;
|
||||
}CoAPList;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short message_id;
|
||||
NetworkContext *p_network;
|
||||
CoAPEventNotifier notifier;
|
||||
unsigned char *sendbuf;
|
||||
unsigned char *recvbuf;
|
||||
CoAPList sendlist;
|
||||
CoAPList obsserver;
|
||||
CoAPList obsclient;
|
||||
CoAPList resource;
|
||||
unsigned int waittime;
|
||||
void *appdata;
|
||||
void *mutex;
|
||||
}CoAPIntContext;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,675 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPSerialize.h"
|
||||
#include "CoAPDeserialize.h"
|
||||
#include "CoAPResource.h"
|
||||
#include "CoAPObserve.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPInternal.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#define COAPAckMsg(header) \
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) \
|
||||
&&(header.type == COAP_MESSAGE_TYPE_ACK))
|
||||
|
||||
#define CoAPRespMsg(header)\
|
||||
((header.code >= 0x40) && (header.code < 0xc0))
|
||||
|
||||
#define CoAPPingMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_EMPTY_MESSAGE)\
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define CoAPResetMsg(header)\
|
||||
(header.type == COAP_MESSAGE_TYPE_RST)
|
||||
|
||||
#define CoAPCONRespMsg(header)\
|
||||
((header.code == COAP_MSG_CODE_205_CONTENT) \
|
||||
&& (header.type == COAP_MESSAGE_TYPE_CON))
|
||||
|
||||
#define CoAPReqMsg(header)\
|
||||
((1 <= header.code) && (32 > header.code))
|
||||
|
||||
|
||||
#define NOKEEP 0
|
||||
#define KEEPING 1
|
||||
#define TOREMOVEKEEP 2
|
||||
#define COAP_CUR_VERSION 1
|
||||
#define COAP_MAX_MESSAGE_ID 65535
|
||||
#define COAP_MAX_RETRY_COUNT 8
|
||||
#define COAP_ACK_TIMEOUT 600
|
||||
#define COAP_ACK_RANDOM_FACTOR 1
|
||||
|
||||
unsigned short CoAPMessageId_gen(CoAPContext *context)
|
||||
{
|
||||
unsigned short msg_id = 0;
|
||||
CoAPIntContext *ctx = NULL;
|
||||
if (!context) {
|
||||
return msg_id;
|
||||
}
|
||||
ctx = (CoAPIntContext *)context;
|
||||
HAL_MutexLock(ctx->mutex);
|
||||
msg_id = ((COAP_MAX_MESSAGE_ID == ctx->message_id) ? (ctx->message_id = 1) : ctx->message_id++);
|
||||
HAL_MutexUnlock(ctx->mutex);
|
||||
return msg_id;
|
||||
}
|
||||
|
||||
int CoAPMessageHandler_set(CoAPMessage *message, CoAPSendMsgHandler handler)
|
||||
{
|
||||
if (NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
message->handler = handler;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int CoAPMessageList_add(CoAPContext *context, NetworkAddr *remote,
|
||||
CoAPMessage *message, unsigned char *buffer, int len)
|
||||
{
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
CoAPSendNode *node = NULL;
|
||||
uint64_t tick ;
|
||||
node = coap_malloc(sizeof(CoAPSendNode));
|
||||
|
||||
if (NULL != node) {
|
||||
memset(node, 0x00, sizeof(CoAPSendNode));
|
||||
node->acked = 0;
|
||||
node->user = message->user;
|
||||
node->header = message->header;
|
||||
node->handler = message->handler;
|
||||
node->msglen = len;
|
||||
node->message = buffer;
|
||||
node->timeout_val = COAP_ACK_TIMEOUT * COAP_ACK_RANDOM_FACTOR;
|
||||
memcpy(&node->remote, remote, sizeof(NetworkAddr));
|
||||
if (platform_is_multicast((const char *)remote->addr) || 1 == message->keep) {
|
||||
COAP_FLOW("The message %d need keep", message->header.msgid);
|
||||
node->keep = KEEPING;
|
||||
} else {
|
||||
node->keep = NOKEEP;
|
||||
}
|
||||
|
||||
tick = HAL_UptimeMs ();
|
||||
|
||||
if (COAP_MESSAGE_TYPE_CON == message->header.type) {
|
||||
node->timeout = node->timeout_val + tick;
|
||||
node->retrans_count = COAP_MAX_RETRY_COUNT;
|
||||
} else {
|
||||
node->timeout = node->timeout_val * 4 + tick;
|
||||
node->retrans_count = 0;
|
||||
}
|
||||
|
||||
memcpy(node->token, message->token, message->header.tokenlen);
|
||||
|
||||
HAL_MutexLock(ctx->sendlist.list_mutex);
|
||||
if (ctx->sendlist.count >= ctx->sendlist.maxcount) {
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
coap_free(node);
|
||||
COAP_INFO("The send list is full");
|
||||
return COAP_ERROR_DATA_SIZE;
|
||||
} else {
|
||||
list_add_tail(&node->sendlist, &ctx->sendlist.list);
|
||||
ctx->sendlist.count ++;
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CoAPMessageToken_dump(unsigned char *token, unsigned char tokenlen)
|
||||
{
|
||||
int index = 0, count = 0;
|
||||
int total = 2 * COAP_MSG_MAX_TOKEN_LEN;
|
||||
char buff[2 * COAP_MSG_MAX_TOKEN_LEN + 1] = {0}, *ptr = NULL;
|
||||
|
||||
ptr = buff;
|
||||
for (index = 0; index < tokenlen; index++) {
|
||||
count = HAL_Snprintf(ptr, total, "%02X", token[index]);
|
||||
ptr += count;
|
||||
total -= count;
|
||||
}
|
||||
|
||||
COAP_FLOW("Token Len : %d", tokenlen);
|
||||
COAP_FLOW("Token : %s", buff);
|
||||
}
|
||||
|
||||
void CoAPMessage_dump(NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
unsigned int ctype;
|
||||
unsigned char code, msgclass, detail;
|
||||
|
||||
if (NULL == remote || NULL == message) {
|
||||
return;
|
||||
}
|
||||
code = (unsigned char)message->header.code;
|
||||
msgclass = code >> 5;
|
||||
detail = code & 0x1F;
|
||||
|
||||
COAP_FLOW("*********Message Info**********");
|
||||
COAP_FLOW("Version : %d", message->header.version);
|
||||
COAP_FLOW("Code : %d.%02d(0x%x)", msgclass, detail, code);
|
||||
COAP_FLOW("Type : 0x%x", message->header.type);
|
||||
COAP_FLOW("Msgid : %d", message->header.msgid);
|
||||
COAP_FLOW("Option : %d", message->optcount);
|
||||
COAP_FLOW("Payload Len : %d", message->payloadlen);
|
||||
|
||||
CoAPMessageToken_dump(message->token, message->header.tokenlen);
|
||||
COAP_FLOW("Remote : %s:%d", remote->addr, remote->port);
|
||||
ret = CoAPUintOption_get(message, COAP_OPTION_CONTENT_FORMAT, &ctype);
|
||||
if (COAP_SUCCESS == ret && NULL != message->payload
|
||||
&& (COAP_CT_APP_OCTET_STREAM != ctype && COAP_CT_APP_CBOR != ctype)) {
|
||||
/* COAP_FLOW("Payload : %s", message->payload); */
|
||||
}
|
||||
|
||||
COAP_FLOW("********************************");
|
||||
|
||||
}
|
||||
|
||||
int CoAPMessage_send(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
unsigned short msglen = 0;
|
||||
unsigned char *buff = NULL;
|
||||
unsigned short readlen = 0;
|
||||
CoAPIntContext *ctx = NULL;
|
||||
|
||||
if (NULL == message || NULL == context) {
|
||||
return (COAP_ERROR_INVALID_PARAM);
|
||||
}
|
||||
|
||||
ctx = (CoAPIntContext *)context;
|
||||
msglen = CoAPSerialize_MessageLength(message);
|
||||
if (COAP_MSG_MAX_PDU_LEN < msglen) {
|
||||
COAP_INFO("The message length %d is too loog", msglen);
|
||||
return COAP_ERROR_DATA_SIZE;
|
||||
}
|
||||
|
||||
buff = (unsigned char *)coap_malloc(msglen);
|
||||
if (NULL == buff) {
|
||||
COAP_INFO("Malloc memory failed");
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
memset(buff, 0x00, msglen);
|
||||
msglen = CoAPSerialize_Message(message, buff, msglen);
|
||||
|
||||
#ifndef COAP_OBSERVE_CLIENT_DISABLE
|
||||
CoAPObsClient_delete(ctx, message);
|
||||
#endif
|
||||
readlen = CoAPNetwork_write(ctx->p_network, remote,
|
||||
buff, (unsigned int)msglen, ctx->waittime);
|
||||
if (msglen == readlen) {/*Send message success*/
|
||||
if (CoAPReqMsg(message->header) || CoAPCONRespMsg(message->header)) {
|
||||
COAP_FLOW("The message id %d len %d send success, add to the list",
|
||||
message->header.msgid, msglen);
|
||||
ret = CoAPMessageList_add(ctx, remote, message, buff, msglen);
|
||||
if (COAP_SUCCESS != ret) {
|
||||
coap_free(buff);
|
||||
COAP_ERR("Add the message %d to list failed", message->header.msgid);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
coap_free(buff);
|
||||
COAP_FLOW("The message %d isn't CON msg, needless to be retransmitted",
|
||||
message->header.msgid);
|
||||
}
|
||||
} else {
|
||||
coap_free(buff);
|
||||
COAP_ERR("CoAP transport write failed, send message %d return %d", message->header.msgid, ret);
|
||||
return COAP_ERROR_WRITE_FAILED;
|
||||
}
|
||||
|
||||
CoAPMessage_dump(remote, message);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessage_cancel(CoAPContext *context, CoAPMessage *message)
|
||||
{
|
||||
CoAPSendNode *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (NULL == context || NULL == message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
|
||||
HAL_MutexLock(ctx->sendlist.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->sendlist.list, sendlist, CoAPSendNode) {
|
||||
if (node->header.msgid == message->header.msgid) {
|
||||
list_del(&node->sendlist);
|
||||
ctx->sendlist.count--;
|
||||
COAP_INFO("Cancel message %d from list, cur count %d",
|
||||
node->header.msgid, ctx->sendlist.count);
|
||||
coap_free(node->message);
|
||||
coap_free(node);
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPMessageId_cancel(CoAPContext *context, unsigned short msgid)
|
||||
{
|
||||
CoAPSendNode *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (NULL == context || NULL == ctx->sendlist.list_mutex) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
HAL_MutexLock(ctx->sendlist.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->sendlist.list, sendlist, CoAPSendNode) {
|
||||
if (NULL != node) {
|
||||
if (node->header.msgid == msgid) {
|
||||
list_del(&node->sendlist);
|
||||
ctx->sendlist.count--;
|
||||
COAP_FLOW("Cancel message %d from list, cur count %d",
|
||||
node->header.msgid, ctx->sendlist.count);
|
||||
coap_free(node->message);
|
||||
coap_free(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int CoAPAckMessage_handle(CoAPContext *context, CoAPMessage *message)
|
||||
{
|
||||
CoAPSendNode *node = NULL, *next;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
HAL_MutexLock(ctx->sendlist.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->sendlist.list, sendlist, CoAPSendNode) {
|
||||
if (node->header.msgid == message->header.msgid) {
|
||||
CoAPSendMsgHandler handler = node->handler;
|
||||
void *user_data = node->user;
|
||||
NetworkAddr remote = {0};
|
||||
memcpy(&remote, &node->remote, sizeof(remote));
|
||||
node->acked = 1;
|
||||
if (CoAPRespMsg(node->header)) { /* CON response message */
|
||||
list_del(&node->sendlist);
|
||||
coap_free(node->message);
|
||||
coap_free(node);
|
||||
ctx->sendlist.count --;
|
||||
COAP_DEBUG("The CON response message %d receive ACK, remove it", message->header.msgid);
|
||||
}
|
||||
if (handler) handler(ctx, COAP_RECV_RESP_SUC, user_data, &remote, NULL);
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int CoAPAckMessage_send(CoAPContext *context, NetworkAddr *remote, unsigned short msgid)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPMessage message;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageId_set(&message, msgid);
|
||||
COAP_DEBUG("Send Ack Response Message");
|
||||
ret = CoAPMessage_send(ctx, remote, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CoAPRestMessage_send(CoAPContext *context, NetworkAddr *remote, unsigned short msgid)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPMessage message;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageType_set(&message, COAP_MESSAGE_TYPE_RST);
|
||||
CoAPMessageId_set(&message, msgid);
|
||||
COAP_DEBUG("Send Rest Pong Message");
|
||||
ret = CoAPMessage_send(ctx, remote, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CoAPErrRespMessage_send(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message,
|
||||
unsigned char err_code)
|
||||
{
|
||||
CoAPMessage response;
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
CoAPMessage_init(&response);
|
||||
CoAPMessageCode_set(&response, err_code);
|
||||
CoAPMessageId_set(&response, message->header.msgid);
|
||||
CoAPMessageToken_set(&response, message->token, message->header.tokenlen);
|
||||
if (COAP_MESSAGE_TYPE_CON == message->header.type) {
|
||||
CoAPMessageType_set(&response, COAP_MESSAGE_TYPE_ACK);
|
||||
} else {
|
||||
CoAPMessageType_set(&response, message->header.type);
|
||||
}
|
||||
COAP_FLOW("Send Error Response Message");
|
||||
ret = CoAPMessage_send(ctx, remote, &response);
|
||||
CoAPMessage_destory(&response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CoAPRespMessage_handle(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
char found = 0;
|
||||
CoAPSendNode *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (COAP_MESSAGE_TYPE_CON == message->header.type) {
|
||||
CoAPAckMessage_send(ctx, remote, message->header.msgid);
|
||||
}
|
||||
|
||||
HAL_MutexLock(ctx->sendlist.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->sendlist.list, sendlist, CoAPSendNode) {
|
||||
if (0 != node->header.tokenlen && node->header.tokenlen == message->header.tokenlen
|
||||
&& 0 == memcmp(node->token, message->token, message->header.tokenlen)) {
|
||||
if (!node->keep) {
|
||||
list_del(&node->sendlist);
|
||||
ctx->sendlist.count--;
|
||||
COAP_FLOW("Remove the message id %d from list", node->header.msgid);
|
||||
} else {
|
||||
COAP_FLOW("Find the message id %d, It need keep", node->header.msgid);
|
||||
}
|
||||
found = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found && NULL != node) {
|
||||
message->user = node->user;
|
||||
/* TODO: comment it */
|
||||
/*
|
||||
if (COAP_MSG_CODE_400_BAD_REQUEST <= message->header.code) {
|
||||
if (NULL != ctx->notifier) {
|
||||
ctx->notifier(message->header.code, remote, message);
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (NULL != node->handler) {
|
||||
CoAPSendMsgHandler handler = node->handler;
|
||||
#ifndef COAP_OBSERVE_CLIENT_DISABLE
|
||||
CoAPObsClient_add(ctx, message, remote, node);
|
||||
#endif
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
COAP_FLOW("Call the response message callback %p", handler);
|
||||
handler(ctx, COAP_REQUEST_SUCCESS, message->user, remote, message);
|
||||
} else {
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
}
|
||||
|
||||
if (!node->keep) {
|
||||
if (NULL != node->message) {
|
||||
coap_free(node->message);
|
||||
}
|
||||
coap_free(node);
|
||||
COAP_DEBUG("The message needless keep, free it");
|
||||
}
|
||||
} else {
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
#ifndef COAP_OBSERVE_CLIENT_DISABLE
|
||||
CoAPObsClient_add(ctx, message, remote, NULL);
|
||||
#endif
|
||||
}
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
#define PACKET_INTERVAL_THRE_MS 800
|
||||
#define PACKET_TRIGGER_NUM 100
|
||||
|
||||
static int CoAPRequestMessage_ack_send(CoAPContext *context, NetworkAddr *remote, unsigned short msgid)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPMessage message;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageId_set(&message, msgid);
|
||||
COAP_INFO("Send Ack Response Message: %d", msgid);
|
||||
ret = CoAPMessage_send(ctx, remote, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CoAPRequestMessage_handle(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
int index = 0;
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPResource *resource = NULL;
|
||||
unsigned char path[COAP_MSG_MAX_PATH_LEN] = {0};
|
||||
unsigned char *tmp = path;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
COAP_FLOW("CoAPRequestMessage_handle: %p", ctx);
|
||||
/* TODO: if need only one callback */
|
||||
for (index = 0; index < message->optcount; index++) {
|
||||
if (COAP_OPTION_URI_PATH == message->options[index].num) {
|
||||
if ((COAP_MSG_MAX_PATH_LEN - 1) >= (tmp - path + message->options[index].len)) {
|
||||
*tmp = '/';
|
||||
tmp += 1;
|
||||
strncpy((char *)tmp, (const char *)message->options[index].val, message->options[index].len);
|
||||
tmp += message->options[index].len;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp("/sys/device/info/notify", (const char *)path)) {
|
||||
COAP_DEBUG("Request path is %s", path);
|
||||
}
|
||||
|
||||
resource = CoAPResourceByPath_get(ctx, (char *)path);
|
||||
if (NULL != resource) {
|
||||
if (NULL != resource->callback) {
|
||||
if (((resource->permission) & (1 << ((message->header.code) - 1))) > 0) {
|
||||
if (message->header.type == COAP_MESSAGE_TYPE_CON) {
|
||||
CoAPRequestMessage_ack_send(ctx, remote, message->header.msgid);
|
||||
}
|
||||
resource->callback(ctx, (char *)path, remote, message);
|
||||
} else {
|
||||
COAP_FLOW("The resource %s isn't allowed", resource->path);
|
||||
ret = CoAPErrRespMessage_send(ctx, remote, message, COAP_MSG_CODE_405_METHOD_NOT_ALLOWED);
|
||||
}
|
||||
} else {
|
||||
COAP_FLOW("The resource %s handler isn't exist", resource->path);
|
||||
ret = CoAPErrRespMessage_send(ctx, remote, message, COAP_MSG_CODE_405_METHOD_NOT_ALLOWED);
|
||||
}
|
||||
} else {
|
||||
COAP_FLOW("The resource %s isn't found", path);
|
||||
ret = CoAPErrRespMessage_send(ctx, remote, message, COAP_MSG_CODE_404_NOT_FOUND);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void CoAPMessage_handle(CoAPContext *context,
|
||||
NetworkAddr *remote,
|
||||
unsigned char *buf,
|
||||
unsigned short datalen)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPMessage message;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
COAP_FLOW("CoAPMessage_handle: %p", ctx);
|
||||
memset(&message, 0x00, sizeof(CoAPMessage));
|
||||
|
||||
ret = CoAPDeserialize_Message(&message, buf, datalen);
|
||||
if (COAP_SUCCESS != ret) {
|
||||
if (NULL != ctx->notifier) {
|
||||
/* TODO: */
|
||||
/* context->notifier(context, event); */
|
||||
}
|
||||
}
|
||||
|
||||
COAP_FLOW("--------Receive a Message------");
|
||||
CoAPMessage_dump(remote, &message);
|
||||
|
||||
if (COAPAckMsg(message.header) || CoAPResetMsg(message.header)) {
|
||||
/* TODO: implement handle client observe */
|
||||
|
||||
/* TODO: if need call response callback */
|
||||
CoAPAckMessage_handle(ctx, &message);
|
||||
|
||||
} else if (CoAPRespMsg(message.header)) {
|
||||
CoAPRespMessage_handle(ctx, remote, &message);
|
||||
} else if (CoAPPingMsg(message.header)) {
|
||||
CoAPRestMessage_send(ctx, remote, message.header.msgid);
|
||||
} else if (CoAPReqMsg(message.header)) {
|
||||
CoAPRequestMessage_handle(ctx, remote, &message);
|
||||
} else {
|
||||
COAP_INFO("Weird packet,drop it");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int CoAPMessage_process(CoAPContext *context, unsigned int timeout)
|
||||
{
|
||||
int len = 0;
|
||||
NetworkAddr remote;
|
||||
char ip_addr[17] = {0};
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (NULL == context) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
HAL_Wifi_Get_IP(ip_addr, NULL);
|
||||
|
||||
while (1) {
|
||||
memset(&remote, 0x00, sizeof(NetworkAddr));
|
||||
memset(ctx->recvbuf, 0x00, COAP_MSG_MAX_PDU_LEN);
|
||||
len = CoAPNetwork_read(ctx->p_network,
|
||||
&remote,
|
||||
ctx->recvbuf,
|
||||
COAP_MSG_MAX_PDU_LEN, timeout);
|
||||
if (strncmp((const char *)ip_addr, (const char *)remote.addr, sizeof(ip_addr)) == 0) /* drop the packet from itself*/
|
||||
continue;
|
||||
if (len > 0) {
|
||||
CoAPMessage_handle(ctx, &remote, ctx->recvbuf, len);
|
||||
} else {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Check_timeout (void *context)
|
||||
{
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
CoAPSendNode *node = NULL, *next = NULL, *timeout_node = NULL;
|
||||
uint64_t tick = HAL_UptimeMs ();
|
||||
do {
|
||||
timeout_node = NULL;
|
||||
HAL_MutexLock(ctx->sendlist.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->sendlist.list, sendlist, CoAPSendNode) {
|
||||
|
||||
if (node->keep != NOKEEP) {
|
||||
continue;
|
||||
}
|
||||
if ((node->retrans_count > 0) || (node->timeout >= tick)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Remove the node from the list*/
|
||||
list_del_init(&node->sendlist);
|
||||
ctx->sendlist.count--;
|
||||
COAP_INFO("Retransmit timeout,remove the message id %d count %d",
|
||||
node->header.msgid, ctx->sendlist.count);
|
||||
#ifndef COAP_OBSERVE_SERVER_DISABLE
|
||||
CoapObsServerAll_delete(ctx, &node->remote);
|
||||
#endif
|
||||
timeout_node = node;
|
||||
break;
|
||||
}
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
|
||||
if (timeout_node) {
|
||||
if(NULL != timeout_node->handler){
|
||||
timeout_node->handler(ctx, COAP_RECV_RESP_TIMEOUT, timeout_node->user, &timeout_node->remote, NULL);
|
||||
}
|
||||
coap_free(timeout_node->message);
|
||||
coap_free(timeout_node);
|
||||
}
|
||||
} while (timeout_node);
|
||||
}
|
||||
|
||||
static void Retansmit (void *context)
|
||||
{
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
CoAPSendNode *node = NULL, *next = NULL;
|
||||
unsigned int ret = 0;
|
||||
|
||||
uint64_t tick = HAL_UptimeMs ();
|
||||
HAL_MutexLock(ctx->sendlist.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->sendlist.list, sendlist, CoAPSendNode) {
|
||||
if (NULL == node || node->timeout > tick ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->retrans_count > 0) {
|
||||
/*If has received ack message, don't resend the message*/
|
||||
if(0 == node->acked){
|
||||
COAP_DEBUG("Retansmit the message id %d len %d", node->header.msgid, node->msglen);
|
||||
ret = CoAPNetwork_write(ctx->p_network, &node->remote, node->message, node->msglen, ctx->waittime);
|
||||
if (ret != COAP_SUCCESS) {
|
||||
}
|
||||
}
|
||||
node->timeout_val = node->timeout_val * 3 / 2;
|
||||
-- node->retrans_count;
|
||||
if (node->retrans_count == 0) {
|
||||
node->timeout = tick + COAP_ACK_TIMEOUT;
|
||||
} else {
|
||||
node->timeout = tick + node->timeout_val;
|
||||
}
|
||||
|
||||
COAP_FLOW("node->timeout_val = %d , node->timeout=%d ,tick=%d", node->timeout_val,node->timeout,tick);
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->sendlist.list_mutex);
|
||||
}
|
||||
|
||||
extern void *coap_yield_mutex;
|
||||
|
||||
int CoAPMessage_cycle(CoAPContext *context)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (NULL == context) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (coap_yield_mutex != NULL) {
|
||||
HAL_MutexLock(coap_yield_mutex);
|
||||
}
|
||||
|
||||
res = CoAPMessage_process(ctx, ctx->waittime);
|
||||
Retansmit (ctx);
|
||||
Check_timeout (ctx);
|
||||
|
||||
if (coap_yield_mutex != NULL) {
|
||||
HAL_MutexUnlock(coap_yield_mutex);
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
HAL_SleepMs(20);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __COAP_MESSAGE_H__
|
||||
#define __COAP_MESSAGE_H__
|
||||
#include "CoAPExport.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoAPMsgHeader header;
|
||||
unsigned char retrans_count;
|
||||
unsigned char token[COAP_MSG_MAX_TOKEN_LEN];
|
||||
unsigned long long timeout;
|
||||
unsigned short timeout_val;
|
||||
unsigned int msglen;
|
||||
CoAPSendMsgHandler handler;
|
||||
NetworkAddr remote;
|
||||
struct list_head sendlist;
|
||||
void *user;
|
||||
unsigned char *message;
|
||||
int acked;
|
||||
int keep;
|
||||
} CoAPSendNode;
|
||||
|
||||
|
||||
int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short datalen);
|
||||
|
||||
int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short *datalen);
|
||||
|
||||
int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned int data);
|
||||
|
||||
int CoAPUintOption_get(CoAPMessage *message,
|
||||
unsigned short optnum,
|
||||
unsigned int *data);
|
||||
|
||||
int CoAPOption_present(CoAPMessage *message, unsigned short option);
|
||||
|
||||
|
||||
unsigned short CoAPMessageId_gen(CoAPContext *context);
|
||||
|
||||
int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid);
|
||||
|
||||
int CoAPMessageType_set(CoAPMessage *message, unsigned char type);
|
||||
|
||||
int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code);
|
||||
|
||||
int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
|
||||
unsigned char tokenlen);
|
||||
|
||||
int CoAPMessageUserData_set(CoAPMessage *message, void *userdata);
|
||||
|
||||
int CoAPMessageKeep_Set(CoAPMessage *message, int keep);
|
||||
|
||||
int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
|
||||
unsigned short payloadlen);
|
||||
|
||||
int CoAPMessageHandler_set(CoAPMessage *message, CoAPSendMsgHandler handler);
|
||||
|
||||
int CoAPMessage_init(CoAPMessage *message);
|
||||
|
||||
int CoAPMessage_destory(CoAPMessage *message);
|
||||
|
||||
int CoAPMessage_send(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message);
|
||||
|
||||
int CoAPMessage_recv(CoAPContext *context, unsigned int timeout, int readcount);
|
||||
|
||||
int CoAPMessage_retransmit(CoAPContext *context);
|
||||
|
||||
int CoAPMessage_process(CoAPContext *context, unsigned int timeout);
|
||||
|
||||
int CoAPMessage_cycle(CoAPContext *context);
|
||||
|
||||
int CoAPMessage_cancel(CoAPContext *context, CoAPMessage *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPNetwork.h"
|
||||
|
||||
int CoAPNetwork_read(NetworkContext *p_context,
|
||||
NetworkAddr *p_remote,
|
||||
unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout_ms)
|
||||
|
||||
{
|
||||
int len = 0;
|
||||
NetworkConf *network = NULL;
|
||||
|
||||
if (NULL == p_context || NULL == p_remote || NULL == p_data) {
|
||||
return -1; /* TODO */
|
||||
}
|
||||
|
||||
network = (NetworkConf *)p_context;
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_NETWORK_DTLS == network->type) {
|
||||
} else {
|
||||
#endif
|
||||
len = HAL_UDP_recvfrom(network->fd, p_remote, p_data,
|
||||
datalen, timeout_ms);
|
||||
/* COAP_DEBUG("[CoAP-NWK]: Network read return %d", len); */
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
int CoAPNetwork_write(NetworkContext *p_context,
|
||||
NetworkAddr *p_remote,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout_ms)
|
||||
|
||||
{
|
||||
|
||||
int len = 0;
|
||||
NetworkConf *network = NULL;
|
||||
|
||||
if (NULL == p_context || NULL == p_remote || NULL == p_data) {
|
||||
return -1; /* TODO */
|
||||
}
|
||||
|
||||
network = (NetworkConf *)p_context;
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
/* TODO: */
|
||||
if (COAP_NETWORK_DTLS == network->type) {
|
||||
|
||||
} else {
|
||||
#endif
|
||||
len = HAL_UDP_sendto(network->fd, p_remote,
|
||||
p_data, datalen, timeout_ms);
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
NetworkContext *CoAPNetwork_init(const NetworkInit *p_param)
|
||||
{
|
||||
NetworkConf *network = NULL;
|
||||
|
||||
if (NULL == p_param) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
network = coap_malloc(sizeof(NetworkConf));
|
||||
if (NULL == network) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(network, 0x00, sizeof(NetworkConf));
|
||||
network->type = p_param->type;
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_NETWORK_DTLS == network->type) {
|
||||
/* TODO: */
|
||||
coap_free(network);
|
||||
return NULL;
|
||||
} else {
|
||||
#endif
|
||||
/*Create udp socket*/
|
||||
network->port = p_param->port;
|
||||
network->fd = (intptr_t)HAL_UDP_create_without_connect(NULL, network->port);
|
||||
if ((intptr_t) - 1 == network->fd) {
|
||||
coap_free(network);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HAL_UDP_joinmulticast(network->fd, p_param->group);
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
return (NetworkContext *)network;
|
||||
}
|
||||
|
||||
|
||||
void CoAPNetwork_deinit(NetworkContext *p_context)
|
||||
{
|
||||
NetworkConf *network = NULL;
|
||||
if (NULL == p_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
network = (NetworkConf *)p_context;
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
if (COAP_NETWORK_DTLS == network->type) {
|
||||
/* TODO: */
|
||||
} else {
|
||||
#endif
|
||||
HAL_UDP_close_without_connect(network->fd);
|
||||
coap_free(p_context);
|
||||
p_context = NULL;
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __CoAPNETWORK_H__
|
||||
#define __CoAPNETWORK_H__
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
typedef enum {
|
||||
COAP_NETWORK_NOSEC = 0,
|
||||
COAP_NETWORK_DTLS,
|
||||
} CoAPNetworkType;
|
||||
|
||||
typedef struct {
|
||||
CoAPNetworkType type;
|
||||
unsigned short port;
|
||||
intptr_t fd;
|
||||
} NetworkConf;
|
||||
|
||||
typedef void NetworkContext;
|
||||
|
||||
|
||||
typedef struct {
|
||||
CoAPNetworkType type;
|
||||
char *group;
|
||||
unsigned short port;
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
/* TODO: */
|
||||
#endif
|
||||
} NetworkInit;
|
||||
|
||||
NetworkContext *CoAPNetwork_init(const NetworkInit *p_param);
|
||||
|
||||
|
||||
int CoAPNetwork_write(NetworkContext *p_context,
|
||||
NetworkAddr *p_remote,
|
||||
const unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout);
|
||||
|
||||
int CoAPNetwork_read(NetworkContext *p_context,
|
||||
NetworkAddr *p_remote,
|
||||
unsigned char *p_data,
|
||||
unsigned int datalen,
|
||||
unsigned int timeout);
|
||||
|
||||
void CoAPNetwork_deinit(NetworkContext *p_context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPResource.h"
|
||||
#include "CoAPObserve.h"
|
||||
#include "CoAPMessage.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPInternal.h"
|
||||
|
||||
#ifndef COAP_OBSERVE_SERVER_DISABLE
|
||||
int CoAPObsServer_init(CoAPContext *context, unsigned char obs_maxcount)
|
||||
{
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
ctx->obsserver.list_mutex = HAL_MutexCreate();
|
||||
|
||||
HAL_MutexLock(ctx->obsserver.list_mutex);
|
||||
INIT_LIST_HEAD(&ctx->obsserver.list);
|
||||
ctx->obsserver.count = 0;
|
||||
ctx->obsserver.maxcount = obs_maxcount;
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPObsServer_deinit(CoAPContext *context)
|
||||
{
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
CoapObserver *node = NULL, *next = NULL;
|
||||
|
||||
HAL_MutexLock(ctx->obsserver.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->obsserver.list, obslist, CoapObserver) {
|
||||
list_del(&node->obslist);
|
||||
COAP_DEBUG("Delete %s:%d from observe server", node->remote.addr, node->remote.port);
|
||||
coap_free(node);
|
||||
}
|
||||
ctx->obsserver.count = 0;
|
||||
ctx->obsserver.maxcount = 0;
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
|
||||
HAL_MutexDestroy(ctx->obsserver.list_mutex);
|
||||
ctx->obsserver.list_mutex = NULL;
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int CoAPObsServer_add(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *request)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
unsigned int observe;
|
||||
unsigned int acceptype = 0;
|
||||
CoapObserver *obs = NULL;
|
||||
CoAPResource *resource = NULL;
|
||||
CoapObserver *node = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
resource = CoAPResourceByPath_get(ctx, path);
|
||||
|
||||
ret = CoAPUintOption_get(request, COAP_OPTION_OBSERVE, &observe);
|
||||
|
||||
if (NULL != resource && COAP_SUCCESS == ret && 0 == observe) {
|
||||
/*Check if the observe client already exist*/
|
||||
HAL_MutexLock(ctx->obsserver.list_mutex);
|
||||
list_for_each_entry(node, &ctx->obsserver.list, obslist, CoapObserver) {
|
||||
if ((node->p_resource_of_interest == resource) &&
|
||||
(node->remote.port == remote->port) &&
|
||||
(0 == memcmp(node->remote.addr, remote->addr, NETWORK_ADDR_LEN))) {
|
||||
COAP_DEBUG("The observe client %s:%d already exist,update it", node->remote.addr, node->remote.port);
|
||||
memcpy(node->token, request->token, request->header.tokenlen);
|
||||
node->tokenlen = request->header.tokenlen;
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
return COAP_ERROR_OBJ_ALREADY_EXIST;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
|
||||
|
||||
obs = coap_malloc(sizeof(CoapObserver));
|
||||
if (NULL == obs) {
|
||||
COAP_ERR("Allocate memory failed");
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
memset(obs, 0x00, sizeof(CoapObserver));
|
||||
obs->msg_type = request->header.type;
|
||||
obs->p_resource_of_interest = resource;
|
||||
memcpy(&obs->remote, remote, sizeof(NetworkAddr));
|
||||
memcpy(obs->token, request->token, request->header.tokenlen);
|
||||
obs->tokenlen = request->header.tokenlen;
|
||||
|
||||
|
||||
CoAPUintOption_get(request, COAP_OPTION_ACCEPT, &acceptype);
|
||||
obs->ctype = (acceptype == 0) ? COAP_CT_APP_JSON : acceptype;
|
||||
obs->observer_sequence_num = 0;
|
||||
|
||||
/* TODO: */
|
||||
/* CoAPObsServer_find(); */
|
||||
|
||||
HAL_MutexLock(ctx->obsserver.list_mutex);
|
||||
if (ctx->obsserver.count >= ctx->obsserver.maxcount) {
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
coap_free(obs);
|
||||
COAP_INFO("Cur have %d observer, max allow %d", ctx->obsserver.count, ctx->obsserver.maxcount);
|
||||
return COAP_ERROR_DATA_SIZE;
|
||||
} else {
|
||||
list_add_tail(&obs->obslist, &ctx->obsserver.list);
|
||||
ctx->obsserver.count ++;
|
||||
COAP_DEBUG("Create a observe node, cur have %d nodes", ctx->obsserver.count);
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
int CoapObsServer_delete(CoAPContext *context, NetworkAddr *remote,
|
||||
CoAPResource *resource)
|
||||
{
|
||||
CoapObserver *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
HAL_MutexLock(ctx->obsserver.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->obsserver.list, obslist, CoapObserver) {
|
||||
if ((node->p_resource_of_interest == resource) &&
|
||||
(node->remote.port == remote->port) &&
|
||||
(0 == memcmp(node->remote.addr, remote->addr, NETWORK_ADDR_LEN))) {
|
||||
ctx->obsserver.count --;
|
||||
list_del(&node->obslist);
|
||||
COAP_DEBUG("Delete %s:%d from observe server", node->remote.addr, node->remote.port);
|
||||
coap_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoapObsServerAll_delete(CoAPContext *context, NetworkAddr *remote)
|
||||
{
|
||||
CoapObserver *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
HAL_MutexLock(ctx->obsserver.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->obsserver.list, obslist, CoapObserver) {
|
||||
if (NULL != node && (node->remote.port == remote->port) &&
|
||||
(0 == memcmp(node->remote.addr, remote->addr, NETWORK_ADDR_LEN))) {
|
||||
ctx->obsserver.count --;
|
||||
list_del(&node->obslist);
|
||||
COAP_DEBUG("Delete %s:%d from observe server, cur observe count %d",
|
||||
node->remote.addr, node->remote.port, ctx->obsserver.count);
|
||||
coap_free(node);
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int CoAPObsServer_notify(CoAPContext *context,
|
||||
const char *path, unsigned char *payload,
|
||||
unsigned short payloadlen, CoAPDataEncrypt handler)
|
||||
{
|
||||
unsigned int ret = COAP_SUCCESS;
|
||||
CoAPResource *resource = NULL;
|
||||
CoapObserver *node = NULL;
|
||||
CoAPLenString src;
|
||||
CoAPLenString dest;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
resource = CoAPResourceByPath_get(ctx, path);
|
||||
|
||||
if (NULL != resource) {
|
||||
HAL_MutexLock(ctx->obsserver.list_mutex);
|
||||
list_for_each_entry(node, &ctx->obsserver.list, obslist, CoapObserver) {
|
||||
if (node->p_resource_of_interest == resource) {
|
||||
CoAPMessage message;
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageType_set(&message, node->msg_type);
|
||||
CoAPMessageCode_set(&message, COAP_MSG_CODE_205_CONTENT);
|
||||
CoAPMessageId_set(&message, CoAPMessageId_gen(ctx));
|
||||
CoAPMessageHandler_set(&message, NULL);
|
||||
CoAPMessageUserData_set(&message, node->p_resource_of_interest);
|
||||
CoAPMessageToken_set(&message, node->token, node->tokenlen);
|
||||
CoAPUintOption_add(&message, COAP_OPTION_OBSERVE, node->observer_sequence_num++);
|
||||
CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT, node->ctype);
|
||||
CoAPUintOption_add(&message, COAP_OPTION_MAXAGE, resource->maxage);
|
||||
COAP_DEBUG("Send notify message path %s to remote %s:%d ",
|
||||
path, node->remote.addr, node->remote.port);
|
||||
|
||||
memset(&dest, 0x00, sizeof(CoAPLenString));
|
||||
if (NULL != handler) {
|
||||
src.len = payloadlen;
|
||||
src.data = payload;
|
||||
ret = handler(context, path, &node->remote, &message, &src, &dest);
|
||||
if (COAP_SUCCESS == ret) {
|
||||
CoAPMessagePayload_set(&message, dest.data, dest.len);
|
||||
} else {
|
||||
COAP_INFO("Encrypt payload failed");
|
||||
}
|
||||
} else {
|
||||
CoAPMessagePayload_set(&message, payload, payloadlen);
|
||||
}
|
||||
ret = CoAPMessage_send(ctx, &node->remote, &message);
|
||||
if (NULL != handler && 0 != dest.len && NULL != dest.data) {
|
||||
coap_free(dest.data);
|
||||
dest.len = 0;
|
||||
}
|
||||
CoAPMessage_destory(&message);
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(ctx->obsserver.list_mutex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef COAP_OBSERVE_CLIENT_DISABLE
|
||||
int CoAPObsClient_init(CoAPContext *context, unsigned char obs_maxcount)
|
||||
{
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
ctx->obsclient.list_mutex = HAL_MutexCreate();
|
||||
|
||||
HAL_MutexLock(ctx->obsclient.list_mutex);
|
||||
INIT_LIST_HEAD(&ctx->obsclient.list);
|
||||
ctx->obsclient.count = 0;
|
||||
ctx->obsclient.maxcount = obs_maxcount;
|
||||
HAL_MutexUnlock(ctx->obsclient.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPObsClient_deinit(CoAPContext *context)
|
||||
{
|
||||
CoAPObservable *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
HAL_MutexLock(ctx->obsclient.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->obsclient.list, obslist, CoAPObservable) {
|
||||
list_del(&node->obslist);
|
||||
coap_free(node);
|
||||
}
|
||||
ctx->obsclient.count = 0;
|
||||
ctx->obsclient.maxcount = 0;
|
||||
HAL_MutexUnlock(ctx->obsclient.list_mutex);
|
||||
|
||||
HAL_MutexDestroy(ctx->obsclient.list_mutex);
|
||||
ctx->obsclient.list_mutex = NULL;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPObsClient_add(CoAPContext *context, CoAPMessage *message, NetworkAddr *remote, CoAPSendNode *sendnode)
|
||||
{
|
||||
CoAPObservable *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (COAP_SUCCESS == CoAPOption_present(message, COAP_OPTION_OBSERVE)) {
|
||||
COAP_DEBUG("There is Observe option in message, handle it");
|
||||
if (NULL == sendnode) { /* Not the first response */
|
||||
|
||||
HAL_MutexLock(ctx->obsclient.list_mutex);
|
||||
list_for_each_entry(node, &ctx->obsclient.list, obslist, CoAPObservable) {
|
||||
if (0 != node->tokenlen && node->tokenlen == message->header.tokenlen
|
||||
&& 0 == memcmp(node->token, message->token, node->tokenlen)) {
|
||||
CoAPUintOption_get(message, COAP_OPTION_MAXAGE, &node->max_age);
|
||||
if (NULL != node->callback) {
|
||||
COAP_DEBUG("Call the observe client callback %p", node->callback);
|
||||
node->callback(ctx, COAP_REQUEST_SUCCESS, node->userdata, remote, message);
|
||||
} else {
|
||||
COAP_INFO("The observe client callback is NULL");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->obsclient.list_mutex);
|
||||
|
||||
} else {
|
||||
int found = 0;
|
||||
HAL_MutexLock(ctx->obsclient.list_mutex);
|
||||
list_for_each_entry(node, &ctx->obsclient.list, obslist, CoAPObservable) {
|
||||
if (0 != node->tokenlen && node->tokenlen == message->header.tokenlen
|
||||
&& 0 == memcmp(node->token, message->token, node->tokenlen)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found && ctx->obsclient.count < ctx->obsclient.maxcount) {
|
||||
CoAPObservable *newnode = coap_malloc(sizeof(CoAPObservable));
|
||||
if (NULL != newnode) {
|
||||
memset(newnode, 0x00, sizeof(CoAPObservable));
|
||||
newnode->tokenlen = message->header.tokenlen;
|
||||
memcpy(newnode->token, message->token, message->header.tokenlen);
|
||||
memcpy(&newnode->remote, remote, sizeof(NetworkAddr));
|
||||
newnode->callback = sendnode->handler;
|
||||
newnode->userdata = sendnode->user;
|
||||
CoAPUintOption_get(message, COAP_OPTION_MAXAGE, &newnode->max_age);
|
||||
list_add_tail(&newnode->obslist, &ctx->obsclient.list);
|
||||
ctx->obsclient.count ++;
|
||||
COAP_DEBUG("Add a new obsclient");
|
||||
}
|
||||
} else {
|
||||
COAP_INFO("Cur have %d obsclient, max allow %d", ctx->obsclient.count, ctx->obsclient.maxcount);
|
||||
}
|
||||
HAL_MutexUnlock(ctx->obsclient.list_mutex);
|
||||
}
|
||||
} else {
|
||||
HAL_MutexLock(ctx->obsclient.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->obsclient.list, obslist, CoAPObservable) {
|
||||
if (0 != node->tokenlen && node->tokenlen == message->header.tokenlen
|
||||
&& 0 == memcmp(node->token, message->token, node->tokenlen)) {
|
||||
list_del(&node->obslist);
|
||||
ctx->obsclient.count --;
|
||||
coap_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->obsclient.list_mutex);
|
||||
|
||||
}
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPObsClient_delete(CoAPContext *context, CoAPMessage *message)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
unsigned int observe_option = 0;
|
||||
CoAPObservable *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (NULL == ctx || NULL == message) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (COAP_MSG_CODE_GET == message->header.code) {
|
||||
if (COAP_SUCCESS == CoAPOption_present(message, COAP_OPTION_OBSERVE)) {
|
||||
ret = CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &observe_option);
|
||||
if (COAP_SUCCESS == ret && 1 == observe_option) {
|
||||
HAL_MutexLock(ctx->obsclient.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->obsclient.list, obslist, CoAPObservable) {
|
||||
if (0 != node->tokenlen && node->tokenlen == message->header.tokenlen
|
||||
&& 0 == memcmp(node->token, message->token, node->tokenlen)) {
|
||||
list_del(&node->obslist);
|
||||
ctx->obsclient.count --;
|
||||
coap_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(ctx->obsclient.list_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __COAP_OBSERVE_H__
|
||||
#define __COAP_OBSERVE_H__
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPMessage.h"
|
||||
#include "CoAPResource.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NetworkAddr remote;
|
||||
unsigned char token[COAP_MSG_MAX_TOKEN_LEN];
|
||||
unsigned char tokenlen;
|
||||
unsigned char ctype;
|
||||
CoAPResource *p_resource_of_interest;
|
||||
unsigned int observer_sequence_num;
|
||||
CoAPMessageCode msg_type;
|
||||
struct list_head obslist;
|
||||
} CoapObserver;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NetworkAddr remote;
|
||||
unsigned char token[COAP_MSG_MAX_TOKEN_LEN];
|
||||
unsigned char tokenlen;
|
||||
CoAPSendMsgHandler callback;
|
||||
unsigned int max_age;
|
||||
struct list_head obslist;
|
||||
void *userdata;
|
||||
} CoAPObservable;
|
||||
|
||||
int CoAPObsServer_init(CoAPContext *context, unsigned char obs_maxcount);
|
||||
int CoAPObsServer_deinit(CoAPContext *context);
|
||||
|
||||
int CoAPObsServer_add(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *request);
|
||||
int CoapObsServer_delete(CoAPContext *context, NetworkAddr *remote,
|
||||
CoAPResource *resource);
|
||||
int CoapObsServerAll_delete(CoAPContext *context, NetworkAddr *remote);
|
||||
|
||||
int CoAPObsServer_notify(CoAPContext *context,
|
||||
const char *path, unsigned char *payload,
|
||||
unsigned short payloadlen, CoAPDataEncrypt handler);
|
||||
|
||||
int CoAPObsClient_init(CoAPContext *context, unsigned char obs_maxcount);
|
||||
int CoAPObsClient_deinit(CoAPContext *context);
|
||||
int CoAPObsClient_add(CoAPContext *context, CoAPMessage *message, NetworkAddr *remote, CoAPSendNode *sendnode);
|
||||
int CoAPObsClient_delete(CoAPContext *context, CoAPMessage *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
unsigned int platform_aton(const char *ip_str)
|
||||
{
|
||||
int c;
|
||||
unsigned char base;
|
||||
unsigned int val = 0;
|
||||
unsigned int parts[4] = {0};
|
||||
unsigned int *pp = parts;
|
||||
|
||||
c = *ip_str;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, 1-9=decimal.
|
||||
*/
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
|
||||
val = 0;
|
||||
base = 10;
|
||||
if (c == '0') {
|
||||
c = *++ip_str;
|
||||
if (c == 'x' || c == 'X') {
|
||||
base = 16;
|
||||
c = *++ip_str;
|
||||
} else {
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
c = *++ip_str;
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++ip_str;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++ip_str;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && !isspace(c))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
switch (pp - parts + 1) {
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffffUL)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
int platform_is_multicast(const char *ip_str)
|
||||
{
|
||||
unsigned int addr_in;
|
||||
addr_in = platform_aton(ip_str);
|
||||
return (addr_in > 0xE00000FF && addr_in <= 0xEFFFFFFF);
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPResource.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPInternal.h"
|
||||
#include "iotx_coap_internal.h"
|
||||
|
||||
#define COAP_PATH_DEFAULT_SUM_LEN (5)
|
||||
|
||||
int CoAPPathMD5_sum(const char *path, int len, char outbuf[], int outlen)
|
||||
{
|
||||
unsigned char md5[16] = {0};
|
||||
if (!path || !len || !outbuf || !outlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
utils_md5((unsigned char *)path, (size_t)len, md5);
|
||||
memcpy(outbuf, md5, outlen > 16 ? 16 : outlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CoAPResource_init(CoAPContext *context, int res_maxcount)
|
||||
{
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
ctx->resource.list_mutex = HAL_MutexCreate();
|
||||
|
||||
HAL_MutexLock(ctx->resource.list_mutex);
|
||||
INIT_LIST_HEAD(&ctx->resource.list);
|
||||
ctx->resource.count = 0;
|
||||
ctx->resource.maxcount = res_maxcount;
|
||||
HAL_MutexUnlock(ctx->resource.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPResource_deinit(CoAPContext *context)
|
||||
{
|
||||
CoAPResource *node = NULL, *next = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
char tmpbuf[2 * COAP_MAX_PATH_CHECKSUM_LEN + 1] = {0};
|
||||
|
||||
HAL_MutexLock(ctx->resource.list_mutex);
|
||||
list_for_each_entry_safe(node, next, &ctx->resource.list, reslist, CoAPResource) {
|
||||
if (node->path_type == PATH_FILTER && node->filter_path) {
|
||||
coap_free(node->filter_path);
|
||||
}
|
||||
list_del_init(&node->reslist);
|
||||
infra_hex2str((unsigned char *)node->path, COAP_MAX_PATH_CHECKSUM_LEN, tmpbuf);
|
||||
COAP_DEBUG("Release the resource %s", tmpbuf);
|
||||
coap_free(node);
|
||||
}
|
||||
ctx->resource.count = 0;
|
||||
ctx->resource.maxcount = 0;
|
||||
HAL_MutexUnlock(ctx->resource.list_mutex);
|
||||
|
||||
HAL_MutexDestroy(ctx->resource.list_mutex);
|
||||
ctx->resource.list_mutex = NULL;
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
CoAPResource *CoAPResource_create(const char *path, path_type_t path_type, unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage,
|
||||
CoAPRecvMsgHandler callback)
|
||||
{
|
||||
CoAPResource *resource = NULL;
|
||||
|
||||
if (NULL == path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(path) >= COAP_MSG_MAX_PATH_LEN) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
resource = coap_malloc(sizeof(CoAPResource));
|
||||
if (NULL == resource) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(resource, 0x00, sizeof(CoAPResource));
|
||||
if (path_type == PATH_NORMAL) {
|
||||
resource->path_type = PATH_NORMAL;
|
||||
CoAPPathMD5_sum(path, strlen(path), resource->path, COAP_PATH_DEFAULT_SUM_LEN);
|
||||
} else {
|
||||
int len = strlen(path) + 1;
|
||||
resource->filter_path = coap_malloc(len);
|
||||
if (NULL == resource->filter_path) {
|
||||
coap_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
resource->path_type = PATH_FILTER;
|
||||
memset(resource->filter_path, 0, len);
|
||||
strncpy(resource->filter_path, path, strlen(path));
|
||||
|
||||
}
|
||||
resource->callback = callback;
|
||||
resource->ctype = ctype;
|
||||
resource->maxage = maxage;
|
||||
resource->permission = permission;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
int CoAPResource_register(CoAPContext *context, const char *path,
|
||||
unsigned short permission, unsigned int ctype,
|
||||
unsigned int maxage, CoAPRecvMsgHandler callback)
|
||||
{
|
||||
int exist = 0;
|
||||
char path_calc[COAP_PATH_DEFAULT_SUM_LEN] = {0};
|
||||
CoAPResource *node = NULL, *newnode = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
path_type_t type = PATH_NORMAL;
|
||||
|
||||
if (context == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
HAL_MutexLock(ctx->resource.list_mutex);
|
||||
if (ctx->resource.count >= ctx->resource.maxcount) {
|
||||
HAL_MutexUnlock(ctx->resource.list_mutex);
|
||||
COAP_INFO("The resource count exceeds limit, cur %d, max %d",
|
||||
ctx->resource.count, ctx->resource.maxcount);
|
||||
return COAP_ERROR_DATA_SIZE;
|
||||
}
|
||||
|
||||
if (strstr(path, "/#") != NULL) {
|
||||
type = PATH_FILTER;
|
||||
} else {
|
||||
CoAPPathMD5_sum(path, strlen(path), path_calc, COAP_PATH_DEFAULT_SUM_LEN);
|
||||
}
|
||||
|
||||
list_for_each_entry(node, &ctx->resource.list, reslist, CoAPResource) {
|
||||
if (type == PATH_NORMAL && node->path_type == PATH_NORMAL) {
|
||||
if (0 == memcmp(path_calc, node->path, COAP_PATH_DEFAULT_SUM_LEN)) {
|
||||
/*Alread exist, re-write it*/
|
||||
COAP_INFO("CoAPResource_register:Alread exist");
|
||||
exist = 1;
|
||||
node->callback = callback;
|
||||
node->ctype = ctype;
|
||||
node->maxage = maxage;
|
||||
node->permission = permission;
|
||||
COAP_INFO("The resource %s already exist, re-write it", path);
|
||||
break;
|
||||
}
|
||||
} else if (type == PATH_FILTER && node->path_type == PATH_FILTER) {
|
||||
if (strlen(path) == strlen(node->filter_path) && 0 == strncpy((char *)path, node->filter_path, strlen(path))) {
|
||||
/*Alread exist, re-write it*/
|
||||
COAP_INFO("CoAPResource_register:Alread exist");
|
||||
exist = 1;
|
||||
node->callback = callback;
|
||||
node->ctype = ctype;
|
||||
node->maxage = maxage;
|
||||
node->permission = permission;
|
||||
COAP_INFO("The resource %s already exist, re-write it", path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == exist) {
|
||||
newnode = CoAPResource_create(path, type, permission, ctype, maxage, callback);
|
||||
if (NULL != newnode) {
|
||||
COAP_DEBUG("CoAPResource_register, context:%p, new node", ctx);
|
||||
list_add_tail(&newnode->reslist, &ctx->resource.list);
|
||||
ctx->resource.count++;
|
||||
COAP_DEBUG("Register new resource %s success, count: %d", path, ctx->resource.count);
|
||||
} else {
|
||||
COAP_ERR("New resource create failed");
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(ctx->resource.list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int CoAPResource_unregister(CoAPContext *context, const char *path)
|
||||
{
|
||||
COAP_DEBUG("This feature isn't supported");
|
||||
return COAP_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
CoAPResource *CoAPResourceByPath_get(CoAPContext *context, const char *path)
|
||||
{
|
||||
char path_calc[COAP_PATH_DEFAULT_SUM_LEN] = {0};
|
||||
CoAPResource *node = NULL;
|
||||
CoAPIntContext *ctx = (CoAPIntContext *)context;
|
||||
|
||||
if (NULL == context || NULL == path) {
|
||||
COAP_INFO("%s\n", "NULL == context || NULL == path");
|
||||
return NULL;
|
||||
}
|
||||
COAP_FLOW("CoAPResourceByPath_get, context:%p\n", ctx);
|
||||
|
||||
CoAPPathMD5_sum(path, strlen(path), path_calc, COAP_PATH_DEFAULT_SUM_LEN);
|
||||
|
||||
HAL_MutexLock(ctx->resource.list_mutex);
|
||||
list_for_each_entry(node, &ctx->resource.list, reslist, CoAPResource) {
|
||||
if (0 == memcmp(path_calc, node->path, COAP_PATH_DEFAULT_SUM_LEN)) {
|
||||
HAL_MutexUnlock(ctx->resource.list_mutex);
|
||||
COAP_DEBUG("Found the resource: %s", path);
|
||||
return node;
|
||||
}
|
||||
if (node->path_type == PATH_FILTER && strlen(node->filter_path) > 0
|
||||
&& 0 == strncmp(path, node->filter_path, strlen(node->filter_path) - 1)) {
|
||||
HAL_MutexUnlock(ctx->resource.list_mutex);
|
||||
COAP_DEBUG("Found the resource: %s", path);
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
HAL_MutexUnlock(ctx->resource.list_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __COAP_RESOURCE_H__
|
||||
#define __COAP_RESOURCE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "iotx_coap_internal.h"
|
||||
#include "CoAPExport.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define COAP_MAX_PATH_CHECKSUM_LEN (5)
|
||||
|
||||
typedef struct {
|
||||
unsigned short permission;
|
||||
CoAPRecvMsgHandler callback;
|
||||
unsigned int ctype;
|
||||
unsigned int maxage;
|
||||
struct list_head reslist;
|
||||
char path[COAP_MAX_PATH_CHECKSUM_LEN];
|
||||
char *filter_path;
|
||||
path_type_t path_type;
|
||||
} CoAPResource;
|
||||
|
||||
int CoAPResource_init(CoAPContext *context, int res_maxcount);
|
||||
|
||||
int CoAPPathMD5_sum(const char *path, int len, char outbuf[], int outlen);
|
||||
|
||||
int CoAPResource_register(CoAPContext *context, const char *path,
|
||||
unsigned short permission, unsigned int ctype,
|
||||
unsigned int maxage, CoAPRecvMsgHandler callback);
|
||||
|
||||
CoAPResource *CoAPResourceByPath_get(CoAPContext *context, const char *path);
|
||||
|
||||
int CoAPResource_deinit(CoAPContext *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPServer.h"
|
||||
|
||||
#define COAP_INIT_TOKEN (0x01020304)
|
||||
|
||||
static unsigned int g_coap_running = 0;
|
||||
#ifdef COAP_SERV_MULTITHREAD
|
||||
static void *g_coap_thread = NULL;
|
||||
static void *g_semphore = NULL;
|
||||
#endif
|
||||
static CoAPContext *g_context = NULL;
|
||||
|
||||
static unsigned int CoAPServerToken_get(unsigned char *p_encoded_data)
|
||||
{
|
||||
static unsigned int value = COAP_INIT_TOKEN;
|
||||
p_encoded_data[0] = (unsigned char)((value & 0x00FF) >> 0);
|
||||
p_encoded_data[1] = (unsigned char)((value & 0xFF00) >> 8);
|
||||
p_encoded_data[2] = (unsigned char)((value & 0xFF0000) >> 16);
|
||||
p_encoded_data[3] = (unsigned char)((value & 0xFF000000) >> 24);
|
||||
value++;
|
||||
return sizeof(unsigned int);
|
||||
}
|
||||
|
||||
static int CoAPServerPath_2_option(char *uri, CoAPMessage *message)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
char *pstr = NULL;
|
||||
char path[COAP_MSG_MAX_PATH_LEN] = {0};
|
||||
|
||||
if (NULL == uri || NULL == message) {
|
||||
COAP_ERR("Invalid paramter p_path %p, p_message %p", uri, message);
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (COAP_MSG_MAX_PATH_LEN <= strlen(uri)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
COAP_DEBUG("The uri is %s", uri);
|
||||
|
||||
ptr = pstr = uri;
|
||||
while ('\0' != *ptr) {
|
||||
if ('/' == *ptr) {
|
||||
if (ptr != pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, ptr - pstr);
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
pstr = ptr + 1;
|
||||
|
||||
}
|
||||
if ('\0' == *(ptr + 1) && '\0' != *pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, sizeof(path) - 1);
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
ptr ++;
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
void CoAPServer_thread_leave()
|
||||
{
|
||||
g_coap_running = 0;
|
||||
}
|
||||
|
||||
void *coap_yield_mutex = NULL;
|
||||
|
||||
static void *CoAPServer_yield(void *param)
|
||||
{
|
||||
CoAPContext *context = (CoAPContext *)param;
|
||||
COAP_DEBUG("Enter to CoAP daemon task");
|
||||
|
||||
while (g_coap_running) {
|
||||
CoAPMessage_cycle(context);
|
||||
}
|
||||
|
||||
#ifdef COAP_SERV_MULTITHREAD
|
||||
HAL_SemaphorePost(g_semphore);
|
||||
COAP_INFO("Exit the CoAP daemon task, Post semphore");
|
||||
|
||||
HAL_ThreadDelete(NULL);
|
||||
g_coap_thread = NULL;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef void (*func_v_v)(void *);
|
||||
static func_v_v coapserver_timer = NULL;
|
||||
void CoAPServer_add_timer(void (*on_timer)(void *))
|
||||
{
|
||||
coapserver_timer = on_timer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CoAPContext *CoAPServer_init()
|
||||
{
|
||||
CoAPInitParam param = {0};
|
||||
#ifdef COAP_SERV_MULTITHREAD
|
||||
int stack_used;
|
||||
hal_os_thread_param_t task_parms = {0};
|
||||
#endif
|
||||
|
||||
if (NULL == g_context) {
|
||||
param.appdata = NULL;
|
||||
param.group = "224.0.1.187";
|
||||
param.notifier = NULL;
|
||||
param.obs_maxcount = 16;
|
||||
param.res_maxcount = 255;
|
||||
param.port = 5683;
|
||||
param.send_maxcount = 16;
|
||||
param.waittime = 50;
|
||||
|
||||
#ifdef COAP_SERV_MULTITHREAD
|
||||
g_semphore = HAL_SemaphoreCreate();
|
||||
if (NULL == g_semphore) {
|
||||
COAP_ERR("Semaphore Create failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
coap_yield_mutex = HAL_MutexCreate();
|
||||
if (NULL == coap_yield_mutex) {
|
||||
COAP_ERR("coap_yield_mutex Create failed");
|
||||
HAL_SemaphoreDestroy(g_semphore);
|
||||
g_semphore = NULL;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_context = CoAPContext_create(¶m);
|
||||
if (NULL == g_context) {
|
||||
#ifdef COAP_SERV_MULTITHREAD
|
||||
HAL_SemaphoreDestroy(g_semphore);
|
||||
HAL_MutexDestroy(coap_yield_mutex);
|
||||
g_semphore = NULL;
|
||||
coap_yield_mutex = NULL;
|
||||
#endif
|
||||
COAP_ERR("CoAP Context Create failed");
|
||||
return NULL;
|
||||
}
|
||||
#ifdef COAP_SERV_MULTITHREAD
|
||||
g_coap_running = 1;
|
||||
task_parms.stack_size = 4608;
|
||||
task_parms.name = "CoAPServer_yield";
|
||||
HAL_ThreadCreate(&g_coap_thread, CoAPServer_yield, (void *)g_context, &task_parms, &stack_used);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
COAP_INFO("The CoAP Server already init");
|
||||
}
|
||||
|
||||
return (CoAPContext *)g_context;
|
||||
}
|
||||
|
||||
void CoAPServer_deinit(CoAPContext *context)
|
||||
{
|
||||
if (context != g_context) {
|
||||
COAP_INFO("Invalid CoAP Server context");
|
||||
return;
|
||||
}
|
||||
|
||||
COAP_INFO("CoAP Server deinit");
|
||||
g_coap_running = 0;
|
||||
|
||||
#ifdef COAP_SERV_MULTITHREAD
|
||||
if (NULL != g_semphore) {
|
||||
HAL_SemaphoreWait(g_semphore, PLATFORM_WAIT_INFINITE);
|
||||
COAP_INFO("Wait Semaphore, will exit task");
|
||||
HAL_SemaphoreDestroy(g_semphore);
|
||||
g_semphore = NULL;
|
||||
}
|
||||
if (NULL != coap_yield_mutex) {
|
||||
HAL_MutexDestroy(coap_yield_mutex);
|
||||
coap_yield_mutex = NULL;
|
||||
}
|
||||
#endif
|
||||
if (NULL != context) {
|
||||
CoAPContext_free(context);
|
||||
g_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int CoAPServer_register(CoAPContext *context, const char *uri, CoAPRecvMsgHandler callback)
|
||||
{
|
||||
if (NULL == context || g_context != context) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return CoAPResource_register(context, uri, COAP_PERM_GET, COAP_CT_APP_JSON, 60, callback);
|
||||
}
|
||||
|
||||
int CoAPServerMultiCast_send(CoAPContext *context, NetworkAddr *remote, const char *uri, unsigned char *buff,
|
||||
unsigned short len, CoAPSendMsgHandler callback, unsigned short *msgid)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPMessage message;
|
||||
unsigned char tokenlen;
|
||||
unsigned char token[COAP_MSG_MAX_TOKEN_LEN] = {0};
|
||||
|
||||
if (NULL == context || g_context != context || NULL == remote
|
||||
|| NULL == uri || NULL == buff || NULL == msgid) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
||||
CoAPMessage_init(&message);
|
||||
CoAPMessageType_set(&message, COAP_MESSAGE_TYPE_NON);
|
||||
CoAPMessageCode_set(&message, COAP_MSG_CODE_POST);
|
||||
CoAPMessageId_set(&message, CoAPMessageId_gen(context));
|
||||
tokenlen = CoAPServerToken_get(token);
|
||||
CoAPMessageToken_set(&message, token, tokenlen);
|
||||
CoAPMessageHandler_set(&message, callback);
|
||||
CoAPMessageKeep_Set(&message, 1);
|
||||
|
||||
CoAPServerPath_2_option((char *)uri, &message);
|
||||
CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_JSON);
|
||||
CoAPMessagePayload_set(&message, buff, len);
|
||||
if (msgid) *msgid = message.header.msgid;
|
||||
ret = CoAPMessage_send(context, remote, &message);
|
||||
|
||||
CoAPMessage_destory(&message);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CoAPServerResp_send(CoAPContext *context, NetworkAddr *remote, unsigned char *buff, unsigned short len, void *req,
|
||||
const char *paths, CoAPSendMsgHandler callback, unsigned short *msgid, char qos)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
CoAPMessage response;
|
||||
unsigned int observe = 0;
|
||||
CoAPMessage *request = (CoAPMessage *)req;
|
||||
|
||||
if (NULL == context || g_context != context || NULL == remote
|
||||
|| NULL == buff || NULL == paths || NULL == req) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
CoAPMessage_init(&response);
|
||||
CoAPMessageType_set(&response, qos == 0 ? COAP_MESSAGE_TYPE_NON :COAP_MESSAGE_TYPE_CON);
|
||||
CoAPMessageCode_set(&response, COAP_MSG_CODE_205_CONTENT);
|
||||
CoAPMessageId_set(&response, request->header.msgid);
|
||||
CoAPMessageToken_set(&response, request->token, request->header.tokenlen);
|
||||
CoAPMessageHandler_set(&response, callback);
|
||||
if (msgid) *msgid = response.header.msgid;
|
||||
|
||||
ret = CoAPUintOption_get(request, COAP_OPTION_OBSERVE, &observe);
|
||||
if (COAP_SUCCESS == ret && 0 == observe) {
|
||||
CoAPObsServer_add(context, paths, remote, request);
|
||||
CoAPUintOption_add(&response, COAP_OPTION_OBSERVE, 0);
|
||||
}
|
||||
|
||||
CoAPUintOption_add(&response, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_JSON);
|
||||
CoAPMessagePayload_set(&response, buff, len);
|
||||
|
||||
COAP_DEBUG("Send a response message");
|
||||
ret = CoAPMessage_send(context, remote, &response);
|
||||
CoAPMessage_destory(&response);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CoAPServer_loop(CoAPContext *context)
|
||||
{
|
||||
if (g_context != context || 1 == g_coap_running) {
|
||||
COAP_INFO("The CoAP Server is already running");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef COAP_SERV_MULTITHREAD
|
||||
g_coap_running = 1;
|
||||
CoAPServer_yield((void *)context);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __COAP_SERVER_H__
|
||||
#define __COAP_SERVER_H__
|
||||
|
||||
#include "CoAPExport.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#define COAP_SERV_MULTITHREAD
|
||||
|
||||
CoAPContext *CoAPServer_init();
|
||||
|
||||
void CoAPServer_add_timer (void (*on_timer)(void*));
|
||||
void CoAPServer_loop(CoAPContext *context);
|
||||
|
||||
void CoAPServer_deinit(CoAPContext *context);
|
||||
|
||||
int CoAPServer_register(CoAPContext *context, const char *uri, CoAPRecvMsgHandler callback);
|
||||
|
||||
int CoAPServerMultiCast_send(CoAPContext *context, NetworkAddr *remote, const char *uri,
|
||||
unsigned char *buff, unsigned short len, CoAPSendMsgHandler callback, unsigned short *msgid);
|
||||
|
||||
int CoAPServerResp_send(CoAPContext *context, NetworkAddr *remote, unsigned char *buff, unsigned short len, void *req,
|
||||
const char *paths, CoAPSendMsgHandler callback, unsigned short *msgid, char qos);
|
||||
|
||||
void CoAPServer_thread_leave();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
DLL_IOT_API int awss_report_cloud(void);
|
||||
|
||||
/**
|
||||
** @brief check reset flag in perisistent storage.
|
||||
**
|
||||
** @retval -1 : failure
|
||||
** @retval 0 : sucess
|
||||
** @note
|
||||
** check reset flag in perisistent storage, if device failed to report reset message last time, retry it.
|
||||
**/
|
||||
DLL_IOT_API int awss_check_reset(void);
|
||||
|
||||
/**
|
||||
** @brief report reset to cloud.
|
||||
**
|
||||
** @retval -1 : failure
|
||||
** @retval 0 : sucess
|
||||
** @note
|
||||
** device will save reset flag if device dosen't connect cloud, device will fails to send reset to cloud.
|
||||
** when connection between device and cloud is ready, device will retry to report reset to cloud.
|
||||
**/
|
||||
DLL_IOT_API int awss_report_reset(void);
|
||||
|
||||
/**
|
||||
** @brief stop to report reset to cloud.
|
||||
**
|
||||
** @retval -1 : failure
|
||||
** @retval 0 : sucess
|
||||
** @note
|
||||
** just stop report reset to cloud without any touch reset flag in flash.
|
||||
**/
|
||||
DLL_IOT_API int awss_stop_report_reset(void);
|
||||
|
||||
DLL_IOT_API int awss_bind_deinit(void);
|
||||
|
||||
/**
|
||||
** @brief deinit bind operation.
|
||||
**
|
||||
** @retval -1 : failure
|
||||
** @retval 0 : sucess
|
||||
** @note
|
||||
** stop report token to cloud and release coap topic and handler.
|
||||
**/
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "wrappers_defs.h"
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#include "iot_import_awss.h"
|
||||
#endif
|
||||
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
|
||||
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
|
||||
int HAL_GetProductSecret(char *product_secret);
|
||||
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
|
||||
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
|
||||
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
|
||||
int HAL_Timer_Stop(void *timer);
|
||||
int HAL_Timer_Start(void *timer, int ms);
|
||||
int HAL_Timer_Delete(void *timer);
|
||||
char *HAL_Wifi_Get_Mac(char mac_str[HAL_MAC_LEN]);
|
||||
void HAL_Srandom(uint32_t seed);
|
||||
uint32_t HAL_Random(uint32_t region);
|
||||
void HAL_Reboot();
|
||||
void *HAL_MutexCreate(void);
|
||||
void HAL_SleepMs(uint32_t ms);
|
||||
void HAL_MutexDestroy(void *mutex);
|
||||
void HAL_MutexLock(void *mutex);
|
||||
void HAL_MutexUnlock(void *mutex);
|
||||
void *HAL_Malloc(uint32_t size);
|
||||
void HAL_Free(void *ptr);
|
||||
int HAL_Sys_Net_Is_Ready();
|
||||
uint64_t HAL_UptimeMs(void);
|
||||
uint32_t HAL_Wifi_Get_IP(char ip_str[NETWORK_ADDR_LEN], const char *ifname);
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
|
||||
int HAL_Awss_Connect_Ap(
|
||||
_IN_ uint32_t connection_timeout_ms,
|
||||
_IN_ char ssid[HAL_MAX_SSID_LEN],
|
||||
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
|
||||
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
|
||||
_IN_OPT_ enum AWSS_ENC_TYPE encry,
|
||||
_IN_OPT_ uint8_t bssid[ETH_ALEN],
|
||||
_IN_OPT_ uint8_t channel);
|
||||
#endif
|
||||
/* dev reset */
|
||||
int HAL_Kv_Set(const char *key, const void *val, int len, int sync);
|
||||
int HAL_Kv_Get(const char *key, void *val, int *buffer_len);
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#ifndef AWSS_DISABLE_REGISTRAR
|
||||
#include "awss_enrollee.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static void *awss_bind_mutex = NULL;
|
||||
int awss_report_cloud()
|
||||
{
|
||||
if (awss_bind_mutex == NULL) {
|
||||
awss_bind_mutex = HAL_MutexCreate();
|
||||
if (awss_bind_mutex == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexLock(awss_bind_mutex);
|
||||
|
||||
awss_cmp_online_init();
|
||||
#ifdef DEVICE_MODEL_ENABLED
|
||||
awss_check_reset();
|
||||
#endif
|
||||
awss_report_token();
|
||||
|
||||
awss_cmp_local_init(AWSS_LC_INIT_BIND);
|
||||
awss_dev_bind_notify_stop();
|
||||
awss_dev_bind_notify();
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#ifndef AWSS_DISABLE_REGISTRAR
|
||||
awss_registrar_init();
|
||||
#endif
|
||||
AWSS_DISP_STATIS();
|
||||
AWSS_REPORT_STATIS("RDA5981");
|
||||
#endif
|
||||
AWSS_DB_DISP_STATIS();
|
||||
AWSS_DB_REPORT_STATIS("RDA5981");
|
||||
HAL_MutexUnlock(awss_bind_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_bind_deinit()
|
||||
{
|
||||
if (awss_bind_mutex) {
|
||||
HAL_MutexLock(awss_bind_mutex);
|
||||
}
|
||||
|
||||
#ifdef DEVICE_MODEL_ENABLED
|
||||
awss_stop_report_reset();
|
||||
#endif
|
||||
awss_stop_report_token();
|
||||
awss_cmp_online_deinit();
|
||||
|
||||
awss_dev_bind_notify_stop();
|
||||
|
||||
awss_cmp_local_deinit(1);
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#ifndef AWSS_DISABLE_REGISTRAR
|
||||
awss_registrar_deinit();
|
||||
#endif
|
||||
AWSS_CLEAR_STATIS();
|
||||
#endif
|
||||
AWSS_DB_CLEAR_STATIS();
|
||||
|
||||
if (awss_bind_mutex) {
|
||||
HAL_MutexUnlock(awss_bind_mutex);
|
||||
HAL_MutexDestroy(awss_bind_mutex);
|
||||
}
|
||||
|
||||
awss_bind_mutex = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#ifdef AWSS_SUPPORT_DEV_BIND_STATIS
|
||||
static struct awss_statis_dev_bind_t g_db_statis = {0};
|
||||
static uint32_t awss_statis_db_report_id = 0;
|
||||
static uint32_t awss_statis_db_trace_id = 0;
|
||||
static void *awss_statis_db_mutex = NULL;
|
||||
|
||||
#define DB_CNT g_db_statis.dev_bind_cnt
|
||||
#define DB_SUC g_db_statis.dev_bind_suc
|
||||
#define DB_TMEAN g_db_statis.dev_bind_time_mean
|
||||
#define DB_TMIN g_db_statis.dev_bind_time_min
|
||||
#define DB_TMAX g_db_statis.dev_bind_time_max
|
||||
#define DB_START g_db_statis.dev_bind_start
|
||||
#define DB_END g_db_statis.dev_bind_end
|
||||
|
||||
#define AWSS_STATIS_DB_BUF_LEN (512)
|
||||
|
||||
int awss_bind_report_statis(const char *module)
|
||||
{
|
||||
const char *elem_fmt = "[%s max:%u min:%u mean:%u cnt:%u suc:%u]";
|
||||
int log_buf_len = AWSS_STATIS_DB_BUF_LEN + strlen(AWSS_STATIS_FMT) + 21;
|
||||
char statis_topic[TOPIC_LEN_MAX] = {0};
|
||||
char *log_content = NULL;
|
||||
char id_str[21] = {0};
|
||||
char *log_buf = NULL;
|
||||
int len = 0;
|
||||
int ret;
|
||||
|
||||
log_content = os_zalloc(AWSS_STATIS_DB_BUF_LEN + 1);
|
||||
if (log_content == NULL) {
|
||||
goto BIND_STATIS_ERR;
|
||||
}
|
||||
log_buf = os_zalloc(log_buf_len + 1);
|
||||
if (log_buf == NULL) {
|
||||
goto BIND_STATIS_ERR;
|
||||
}
|
||||
|
||||
if (awss_build_topic(TOPIC_POST_STATIS, statis_topic, TOPIC_LEN_MAX) == NULL) {
|
||||
awss_err("awss build statis topic fail\n");
|
||||
goto BIND_STATIS_ERR;
|
||||
}
|
||||
|
||||
if (awss_statis_db_mutex) {
|
||||
HAL_MutexLock(awss_statis_db_mutex);
|
||||
}
|
||||
do {
|
||||
if (DB_CNT == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "SyncToken",
|
||||
DB_TMAX, DB_TMIN, DB_TMEAN, DB_CNT, DB_SUC);
|
||||
|
||||
HAL_Snprintf(log_content, AWSS_STATIS_DB_BUF_LEN, AWSS_STATIS_FMT, (uint32_t)HAL_UptimeMs(), "BIND_TRACE",
|
||||
module == NULL ? "default" : module, awss_statis_db_trace_id, log_buf);
|
||||
|
||||
HAL_Snprintf(id_str, sizeof(id_str), "%u", ++ awss_statis_db_report_id);
|
||||
|
||||
awss_build_packet(AWSS_CMP_PKT_TYPE_REQ, id_str, ILOP_VER, METHOD_LOG_POST, log_content, 0,
|
||||
log_buf, &log_buf_len);
|
||||
|
||||
awss_debug("%s\n", log_buf);
|
||||
|
||||
ret = awss_cmp_mqtt_send(statis_topic, log_buf, strlen(log_buf), 0);
|
||||
|
||||
awss_info("bind report statis %s\n", ret == 0 ? "success" : "fail");
|
||||
} while (0);
|
||||
|
||||
if (awss_statis_db_mutex) {
|
||||
HAL_MutexUnlock(awss_statis_db_mutex);
|
||||
}
|
||||
|
||||
HAL_Free(log_buf);
|
||||
HAL_Free(log_content);
|
||||
|
||||
return 0;
|
||||
|
||||
BIND_STATIS_ERR:
|
||||
if (log_content) {
|
||||
HAL_Free(log_content);
|
||||
}
|
||||
if (log_buf) {
|
||||
HAL_Free(log_buf);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void awss_bind_clear_statis()
|
||||
{
|
||||
if (awss_statis_db_mutex) {
|
||||
HAL_MutexLock(awss_statis_db_mutex);
|
||||
}
|
||||
|
||||
memset(&g_db_statis, 0, sizeof(g_db_statis));
|
||||
|
||||
awss_statis_db_trace_id = 0;
|
||||
awss_statis_db_report_id = 0;
|
||||
|
||||
if (awss_statis_db_mutex) {
|
||||
HAL_MutexUnlock(awss_statis_db_mutex);
|
||||
HAL_MutexDestroy(awss_statis_db_mutex);
|
||||
}
|
||||
awss_statis_db_mutex = NULL;
|
||||
}
|
||||
|
||||
void awss_bind_update_statis(int type)
|
||||
{
|
||||
uint32_t time = HAL_UptimeMs();
|
||||
|
||||
if (awss_statis_db_mutex == NULL) {
|
||||
awss_statis_db_mutex = HAL_MutexCreate();
|
||||
if (awss_statis_db_mutex == NULL) {
|
||||
awss_debug("a-statis am fail\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexLock(awss_statis_db_mutex);
|
||||
|
||||
if (type == AWSS_DB_STATIS_START) {
|
||||
awss_statis_db_trace_id ++;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case AWSS_DB_STATIS_START:
|
||||
DB_CNT ++;
|
||||
DB_START = time;
|
||||
break;
|
||||
case AWSS_DB_STATIS_SUC:
|
||||
DB_END = time;
|
||||
DB_SUC ++;
|
||||
time = (uint32_t)(DB_END - DB_START);
|
||||
if (DB_SUC > 0) {
|
||||
DB_TMEAN = (DB_TMEAN + time) / DB_SUC;
|
||||
} else {
|
||||
DB_SUC = 1;
|
||||
DB_TMEAN = time;
|
||||
}
|
||||
if (DB_TMIN == 0 || DB_TMIN > time) {
|
||||
DB_TMIN = time;
|
||||
}
|
||||
if (DB_TMAX == 0 || DB_TMAX < time) {
|
||||
DB_TMAX = time;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
HAL_MutexUnlock(awss_statis_db_mutex);
|
||||
}
|
||||
|
||||
void awss_bind_disp_statis()
|
||||
{
|
||||
if (awss_statis_db_mutex) {
|
||||
HAL_MutexLock(awss_statis_db_mutex);
|
||||
}
|
||||
|
||||
awss_debug("--------------------------DEV BIND STATIS-----------------------------");
|
||||
awss_debug("name\t\tmax\tmin\tmean\tcnt\tsuc");
|
||||
awss_debug("SyncToken \t%u\t%u\t%u\t%u\t%u\t",
|
||||
DB_TMAX, DB_TMIN, DB_TMEAN, DB_CNT, DB_SUC);
|
||||
awss_debug("----------------------------------------------------------------------");
|
||||
|
||||
if (awss_statis_db_mutex) {
|
||||
HAL_MutexUnlock(awss_statis_db_mutex);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_BIND_STATIS_H__
|
||||
#define __AWSS_BIND_STATIS_H__
|
||||
|
||||
#ifndef AWSS_SUPPORT_DEV_BIND_STATIS
|
||||
#define AWSS_SUPPORT_DEV_BIND_STATIS
|
||||
#endif
|
||||
|
||||
enum {
|
||||
AWSS_DB_STATIS_START,
|
||||
AWSS_DB_STATIS_SUC,
|
||||
};
|
||||
|
||||
#ifdef AWSS_SUPPORT_DEV_BIND_STATIS
|
||||
struct awss_statis_dev_bind_t {
|
||||
uint32_t dev_bind_cnt; /* the count of token sync */
|
||||
uint32_t dev_bind_suc; /* the successful count of token sync */
|
||||
uint32_t dev_bind_time_mean; /* the mean time of token sync */
|
||||
uint32_t dev_bind_time_max; /* the max time of token sync */
|
||||
uint32_t dev_bind_time_min; /* the min time of token sync */
|
||||
uint32_t dev_bind_start; /* the start time to sync token */
|
||||
uint32_t dev_bind_end; /* the end time of token sync */
|
||||
}; /* statistics for token sync */
|
||||
|
||||
|
||||
int awss_bind_report_statis(const char *module);
|
||||
void awss_bind_update_statis(int type);
|
||||
void awss_bind_clear_statis();
|
||||
void awss_bind_disp_statis();
|
||||
|
||||
|
||||
#define AWSS_DB_UPDATE_STATIS(type) awss_bind_update_statis(type)
|
||||
#define AWSS_DB_DISP_STATIS() awss_bind_disp_statis()
|
||||
#define AWSS_DB_CLEAR_STATIS() awss_bind_clear_statis()
|
||||
#define AWSS_DB_REPORT_STATIS(m) awss_bind_report_statis(m)
|
||||
#else
|
||||
#define AWSS_DB_UPDATE_STATIS(type)
|
||||
#define AWSS_DB_DISP_STATIS()
|
||||
#define AWSS_DB_CLEAR_STATIS()
|
||||
#define AWSS_DB_REPORT_STATIS(m)
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_CMP_H__
|
||||
#define __AWSS_CMP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* @brief this is a network address structure, including host(ip or host name) and port.
|
||||
*/
|
||||
typedef struct {
|
||||
char host[16]; /**< host ip(dotted-decimal notation) or host name(string) */
|
||||
uint16_t port; /**< udp port or tcp port */
|
||||
} platform_netaddr_t;
|
||||
|
||||
enum {
|
||||
AWSS_LC_INIT_ROUTER = 0x01,
|
||||
AWSS_LC_INIT_PAP = 0x02,
|
||||
AWSS_LC_INIT_DEV_AP = 0x04,
|
||||
AWSS_LC_INIT_SUC = 0x08,
|
||||
AWSS_LC_INIT_BIND = 0x100,
|
||||
};
|
||||
|
||||
struct awss_cmp_couple {
|
||||
int init_stage;
|
||||
char *topic;
|
||||
void *cb;
|
||||
};
|
||||
|
||||
struct coap_session_ctx_t {
|
||||
void *request;
|
||||
void *remote;
|
||||
char is_mcast;
|
||||
};
|
||||
|
||||
int awss_cmp_local_init(int init_stage);
|
||||
int awss_cmp_local_deinit(int force);
|
||||
int awss_cmp_online_init();
|
||||
int awss_cmp_online_deinit();
|
||||
int awss_token_remain_time();
|
||||
int awss_token_timeout();
|
||||
int awss_update_token();
|
||||
int awss_report_token();
|
||||
int awss_stop_report_token();
|
||||
|
||||
int awss_cmp_coap_cancel_packet(uint16_t msgid);
|
||||
int awss_cmp_coap_register_cb(char *topic, void *cb);
|
||||
int awss_cmp_coap_send(void *buf, uint32_t len, void *sa, const char *uri, void *cb, uint16_t *msgid);
|
||||
int awss_cmp_coap_send_resp(void *buf, uint32_t len, void *sa, const char *uri, void* req, void *cb, uint16_t *msgid, char qos);
|
||||
int awss_cmp_coap_ob_send(void *buf, uint32_t len, void *sa, const char *uri, void *cb);
|
||||
int awss_cmp_coap_deinit();
|
||||
|
||||
int awss_cmp_mqtt_register_cb(char *topic, void *cb);
|
||||
int awss_cmp_mqtt_unregister_cb(char *topic);
|
||||
int awss_cmp_mqtt_send(char *topic, void *pkt, int pkt_len, int qos);
|
||||
|
||||
int awss_release_coap_ctx(void *session);
|
||||
void *awss_cpy_coap_ctx(void *request, void *remote, char mcast);
|
||||
|
||||
char *awss_cmp_get_coap_payload(void *request, int *payload_len);
|
||||
uint8_t awss_cmp_get_coap_code(void *request);
|
||||
|
||||
int online_dev_bind_monitor(void *ctx, void *resource, void *remote, void *request);
|
||||
|
||||
void awss_enrollee_checkin(void *pcontext, void *pclient, void *msg);
|
||||
void awss_online_switchap(void *pcontext, void *pclient, void *msg);
|
||||
void awss_report_enrollee_reply(void *pcontext, void *pclient, void *msg);
|
||||
void awss_get_cipher_reply(void *pcontext, void *pclient, void *msg);
|
||||
void awss_report_token_reply(void *pcontext, void *pclient, void *msg);
|
||||
int awss_cmp_mqtt_get_payload(void *mesg, char **payload, uint32_t *playload_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
|
||||
#include "awss_wifimgr.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static void *g_coap_ctx = NULL;
|
||||
|
||||
int awss_release_coap_ctx(void *session)
|
||||
{
|
||||
struct coap_session_ctx_t *ctx = (struct coap_session_ctx_t *)session;
|
||||
if (ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->request) {
|
||||
void *payload = ((struct CoAPMessage *)ctx->request)->payload;
|
||||
if (payload) {
|
||||
HAL_Free(payload);
|
||||
}
|
||||
HAL_Free(ctx->request);
|
||||
}
|
||||
if (ctx->remote) {
|
||||
HAL_Free(ctx->remote);
|
||||
}
|
||||
HAL_Free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *awss_cpy_coap_ctx(void *request, void *remote, char mcast)
|
||||
{
|
||||
struct coap_session_ctx_t *ctx = os_zalloc(sizeof(struct coap_session_ctx_t));
|
||||
if (ctx == NULL) {
|
||||
goto CPY_CTX_FAIL;
|
||||
}
|
||||
|
||||
ctx->request = os_zalloc(sizeof(struct CoAPMessage));
|
||||
if (ctx->request == NULL) {
|
||||
goto CPY_CTX_FAIL;
|
||||
}
|
||||
|
||||
memcpy(ctx->request, request, sizeof(struct CoAPMessage));
|
||||
do {
|
||||
char *payload = NULL;
|
||||
int len = 0;
|
||||
struct CoAPMessage *req = (struct CoAPMessage *)ctx->request;
|
||||
|
||||
payload = awss_cmp_get_coap_payload(request, &len);
|
||||
req->payloadlen = len;
|
||||
if (payload == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
req->payload = os_zalloc(len + 1);
|
||||
if (req->payload == NULL) {
|
||||
goto CPY_CTX_FAIL;
|
||||
}
|
||||
|
||||
memcpy(req->payload, payload, len);
|
||||
} while (0);
|
||||
|
||||
ctx->remote = os_zalloc(sizeof(platform_netaddr_t));
|
||||
if (ctx->remote == NULL) {
|
||||
goto CPY_CTX_FAIL;
|
||||
}
|
||||
|
||||
memcpy(ctx->remote, remote, sizeof(platform_netaddr_t));
|
||||
ctx->is_mcast = mcast;
|
||||
|
||||
return ctx;
|
||||
|
||||
CPY_CTX_FAIL:
|
||||
awss_release_coap_ctx(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t awss_cmp_get_coap_code(void *request)
|
||||
{
|
||||
struct CoAPMessage *msg = NULL;
|
||||
if (request == NULL) {
|
||||
return 0x60;
|
||||
}
|
||||
msg = (struct CoAPMessage *)request;
|
||||
return msg->header.code;
|
||||
}
|
||||
|
||||
char *awss_cmp_get_coap_payload(void *request, int *payload_len)
|
||||
{
|
||||
struct CoAPMessage *msg = (struct CoAPMessage *)request;
|
||||
if (request == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg = (struct CoAPMessage *)request;
|
||||
if (payload_len) {
|
||||
*payload_len = msg->payloadlen;
|
||||
}
|
||||
return (char *)msg->payload;
|
||||
}
|
||||
|
||||
int awss_cmp_coap_register_cb(char *topic, void *cb)
|
||||
{
|
||||
if (g_coap_ctx == NULL) {
|
||||
g_coap_ctx = (void *)CoAPServer_init();
|
||||
}
|
||||
|
||||
if (g_coap_ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (topic == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CoAPServer_register(g_coap_ctx, (const char *)topic, (CoAPRecvMsgHandler)cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_cmp_coap_cancel_packet(uint16_t msgid)
|
||||
{
|
||||
if (g_coap_ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return CoAPMessageId_cancel(g_coap_ctx, msgid);
|
||||
}
|
||||
|
||||
int awss_cmp_coap_send(void *buf, uint32_t len, void *sa, const char *uri, void *cb, uint16_t *msgid)
|
||||
{
|
||||
if (g_coap_ctx == NULL) {
|
||||
g_coap_ctx = (void *)CoAPServer_init();
|
||||
} else {
|
||||
CoAPMessageId_cancel(g_coap_ctx, *msgid);
|
||||
}
|
||||
return CoAPServerMultiCast_send(g_coap_ctx, (NetworkAddr *)sa, uri, (uint8_t *)buf,
|
||||
(uint16_t)len, (CoAPSendMsgHandler)cb, msgid);
|
||||
}
|
||||
|
||||
int awss_cmp_coap_send_resp(void *buf, uint32_t len, void *sa, const char *uri, void *req, void *cb, uint16_t *msgid,
|
||||
char qos)
|
||||
{
|
||||
if (g_coap_ctx == NULL) {
|
||||
g_coap_ctx = (void *)CoAPServer_init();
|
||||
}
|
||||
|
||||
return CoAPServerResp_send(g_coap_ctx, (NetworkAddr *)sa, (uint8_t *)buf, (uint16_t)len, req, uri,
|
||||
(CoAPSendMsgHandler)cb, msgid, qos);
|
||||
}
|
||||
|
||||
int awss_cmp_coap_ob_send(void *buf, uint32_t len, void *sa, const char *uri, void *cb)
|
||||
{
|
||||
if (g_coap_ctx == NULL) {
|
||||
g_coap_ctx = (void *)CoAPServer_init();
|
||||
}
|
||||
|
||||
return CoAPObsServer_notify(g_coap_ctx, uri, (uint8_t *)buf, (uint16_t)len, cb);
|
||||
}
|
||||
|
||||
int awss_cmp_coap_deinit()
|
||||
{
|
||||
void *coap_ctx = g_coap_ctx;
|
||||
g_coap_ctx = NULL;
|
||||
|
||||
if (coap_ctx) {
|
||||
CoAPServer_deinit(coap_ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct awss_cmp_couple awss_local_couple[] = {
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
|
||||
{AWSS_LC_INIT_PAP, TOPIC_AWSS_SWITCHAP, wifimgr_process_switch_ap_request},
|
||||
{AWSS_LC_INIT_PAP, TOPIC_AWSS_WIFILIST, wifimgr_process_get_wifilist_request},
|
||||
{AWSS_LC_INIT_ROUTER | AWSS_LC_INIT_PAP, TOPIC_AWSS_GETDEVICEINFO_MCAST, wifimgr_process_mcast_get_device_info},
|
||||
{AWSS_LC_INIT_ROUTER | AWSS_LC_INIT_PAP, TOPIC_AWSS_GETDEVICEINFO_UCAST, wifimgr_process_ucast_get_device_info},
|
||||
#endif
|
||||
#ifdef AWSS_SUPPORT_DEV_AP
|
||||
{AWSS_LC_INIT_DEV_AP, TOPIC_AWSS_DEV_AP_SWITCHAP, wifimgr_process_dev_ap_switchap_request},
|
||||
#endif
|
||||
{AWSS_LC_INIT_SUC, TOPIC_AWSS_GET_CONNECTAP_INFO_MCAST, awss_process_mcast_get_connectap_info},
|
||||
{AWSS_LC_INIT_SUC, TOPIC_AWSS_GET_CONNECTAP_INFO_UCAST, awss_process_ucast_get_connectap_info},
|
||||
#ifndef AWSS_DISABLE_REGISTRAR
|
||||
{AWSS_LC_INIT_BIND, TOPIC_NOTIFY, online_dev_bind_monitor},
|
||||
{AWSS_LC_INIT_BIND, TOPIC_AWSS_CONNECTAP_NOTIFY, online_dev_bind_monitor},
|
||||
#endif
|
||||
#endif
|
||||
{AWSS_LC_INIT_SUC | AWSS_LC_INIT_BIND, TOPIC_GETDEVICEINFO_MCAST, online_mcast_get_device_info},
|
||||
{AWSS_LC_INIT_SUC | AWSS_LC_INIT_BIND, TOPIC_GETDEVICEINFO_UCAST, online_ucast_get_device_info},
|
||||
};
|
||||
|
||||
int awss_cmp_local_init(int init_stage)
|
||||
{
|
||||
char topic[TOPIC_LEN_MAX] = {0};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(awss_local_couple) / sizeof(awss_local_couple[0]); i ++) {
|
||||
if ((awss_local_couple[i].init_stage & init_stage) == 0) {
|
||||
continue;
|
||||
}
|
||||
memset(topic, 0, sizeof(topic));
|
||||
awss_build_topic(awss_local_couple[i].topic, topic, TOPIC_LEN_MAX);
|
||||
awss_cmp_coap_register_cb(topic, awss_local_couple[i].cb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_cmp_local_deinit(int force)
|
||||
{
|
||||
if (g_coap_ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
|
||||
awss_devinfo_notify_stop();
|
||||
#endif
|
||||
awss_suc_notify_stop();
|
||||
#endif
|
||||
if (force) {
|
||||
awss_cmp_coap_deinit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static char online_init = 0;
|
||||
|
||||
int awss_cmp_mqtt_register_cb(char *topic, void *cb)
|
||||
{
|
||||
if (topic == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return IOT_MQTT_Subscribe(NULL, topic, 0, (iotx_mqtt_event_handle_func_fpt)cb, NULL);
|
||||
}
|
||||
|
||||
int awss_cmp_mqtt_unregister_cb(char *topic)
|
||||
{
|
||||
return IOT_MQTT_Unsubscribe(NULL, topic);
|
||||
}
|
||||
|
||||
int awss_cmp_mqtt_send(char *topic, void *data, int len, int qos)
|
||||
{
|
||||
return IOT_MQTT_Publish_Simple(NULL, topic, qos, data, len); /* IOTX_MQTT_QOS1 or IOTX_MQTT_QOS1 */
|
||||
}
|
||||
|
||||
const struct awss_cmp_couple awss_online_couple[] = {
|
||||
{-1, TOPIC_MATCH_REPORT_REPLY, awss_report_token_reply},
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#ifndef AWSS_DISABLE_REGISTRAR
|
||||
{-1, TOPIC_ZC_CHECKIN, awss_enrollee_checkin},
|
||||
{-1, TOPIC_ZC_ENROLLEE_REPLY, awss_report_enrollee_reply},
|
||||
{-1, TOPIC_ZC_CIPHER_REPLY, awss_get_cipher_reply},
|
||||
#endif
|
||||
{-1, TOPIC_SWITCHAP, awss_online_switchap}
|
||||
#endif
|
||||
};
|
||||
|
||||
int awss_cmp_online_init()
|
||||
{
|
||||
int i;
|
||||
char topic[TOPIC_LEN_MAX] = {0};
|
||||
if (online_init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < sizeof(awss_online_couple) / sizeof(awss_online_couple[0]); i ++) {
|
||||
int res = -1;
|
||||
memset(topic, 0, sizeof(topic));
|
||||
awss_build_topic(awss_online_couple[i].topic, topic, TOPIC_LEN_MAX);
|
||||
res = awss_cmp_mqtt_register_cb(topic, awss_online_couple[i].cb);
|
||||
awss_debug("sub %s %s\n", topic, res < 0 ? "fail" : "success");
|
||||
}
|
||||
|
||||
online_init = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_cmp_online_deinit()
|
||||
{
|
||||
uint8_t i;
|
||||
char topic[TOPIC_LEN_MAX] = {0};
|
||||
|
||||
if (!online_init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
awss_dev_bind_notify_stop();
|
||||
|
||||
for (i = 0; i < sizeof(awss_online_couple) / sizeof(awss_online_couple[0]); i ++) {
|
||||
memset(topic, 0, sizeof(topic));
|
||||
awss_build_topic(awss_online_couple[i].topic, topic, TOPIC_LEN_MAX);
|
||||
awss_cmp_mqtt_unregister_cb(topic);
|
||||
}
|
||||
|
||||
online_init = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_cmp_mqtt_get_payload(void *mesg, char **payload, uint32_t *playload_len)
|
||||
{
|
||||
iotx_mqtt_event_msg_pt msg;
|
||||
iotx_mqtt_topic_info_pt ptopic_info;
|
||||
if (mesg == NULL || payload == NULL || playload_len == NULL) {
|
||||
return - 1;
|
||||
}
|
||||
|
||||
msg = (iotx_mqtt_event_msg_pt)mesg;
|
||||
ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;
|
||||
|
||||
|
||||
switch (msg->event_type) {
|
||||
case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
|
||||
*playload_len = ptopic_info->payload_len;
|
||||
*payload = (char *)ptopic_info->payload;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
extern int iotx_event_post(int event);
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int awss_event_post(int event)
|
||||
{
|
||||
int ret = 0;
|
||||
void *cb = NULL;
|
||||
|
||||
ret = iotx_event_post(event);
|
||||
|
||||
cb = (void *)iotx_event_callback(ITE_AWSS_STATUS);
|
||||
if (cb) {
|
||||
ret = ((int (*)(int))cb)(event);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_EVENT_H__
|
||||
#define __AWSS_EVENT_H__
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int awss_event_post(int event);
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
#define AWSS_CONNAP_MONITOR_TIMEOUT_MS (60 * 1000)
|
||||
|
||||
static char g_awss_connectap_info_avaliable = 0;
|
||||
static void *connectap_monitor_timer = NULL;
|
||||
static void *connectap_monitor_mutex = NULL;
|
||||
|
||||
static void awss_release_connectap_monitor()
|
||||
{
|
||||
if (connectap_monitor_timer) {
|
||||
HAL_Timer_Stop(connectap_monitor_timer);
|
||||
HAL_Timer_Delete(connectap_monitor_timer);
|
||||
connectap_monitor_timer = NULL;
|
||||
}
|
||||
if (connectap_monitor_mutex) {
|
||||
HAL_MutexUnlock(connectap_monitor_mutex);
|
||||
HAL_MutexDestroy(connectap_monitor_mutex);
|
||||
connectap_monitor_mutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void awss_connectap_monitor(void *param)
|
||||
{
|
||||
if (connectap_monitor_mutex) {
|
||||
HAL_MutexLock(connectap_monitor_mutex);
|
||||
}
|
||||
g_awss_connectap_info_avaliable = 0;
|
||||
awss_release_connectap_monitor();
|
||||
}
|
||||
|
||||
int awss_stop_connectap_monitor()
|
||||
{
|
||||
awss_connectap_monitor(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_start_connectap_monitor()
|
||||
{
|
||||
if (connectap_monitor_timer) {
|
||||
awss_debug("connap-m exist");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (connectap_monitor_mutex == NULL) {
|
||||
connectap_monitor_mutex = HAL_MutexCreate();
|
||||
if (connectap_monitor_mutex == NULL) {
|
||||
awss_err("connap alloc-m fail");
|
||||
goto CONNAP_M_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexLock(connectap_monitor_mutex);
|
||||
|
||||
connectap_monitor_timer = HAL_Timer_Create("connap_monitor",
|
||||
awss_connectap_monitor, NULL);
|
||||
if (connectap_monitor_timer == NULL) {
|
||||
awss_err("connap alloc-t fail");
|
||||
goto CONNAP_M_FAIL;
|
||||
}
|
||||
|
||||
g_awss_connectap_info_avaliable = 1;
|
||||
HAL_Timer_Stop(connectap_monitor_timer);
|
||||
HAL_Timer_Start(connectap_monitor_timer, AWSS_CONNAP_MONITOR_TIMEOUT_MS);
|
||||
HAL_MutexUnlock(connectap_monitor_mutex);
|
||||
return 0;
|
||||
|
||||
CONNAP_M_FAIL:
|
||||
awss_release_connectap_monitor();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int process_get_device_info(void *ctx, void *resource, void *remote, void *request, char is_mcast, int type)
|
||||
{
|
||||
char *buf = NULL;
|
||||
char *dev_info = NULL;
|
||||
int len = 0, id_len = 0;
|
||||
char *msg = NULL, *id = NULL;
|
||||
const char *topic_fmt = NULL;
|
||||
char topic[TOPIC_LEN_MAX] = {0};
|
||||
char req_msg_id[MSG_REQ_ID_LEN] = {0};
|
||||
|
||||
buf = os_zalloc(DEV_INFO_LEN_MAX);
|
||||
if (!buf) {
|
||||
goto DEV_INFO_ERR;
|
||||
}
|
||||
|
||||
dev_info = os_zalloc(DEV_INFO_LEN_MAX);
|
||||
if (!dev_info) {
|
||||
goto DEV_INFO_ERR;
|
||||
}
|
||||
|
||||
msg = awss_cmp_get_coap_payload(request, &len);
|
||||
id = json_get_value_by_name(msg, len, "id", &id_len, 0);
|
||||
if (id && id_len < MSG_REQ_ID_LEN) {
|
||||
memcpy(req_msg_id, id, id_len);
|
||||
}
|
||||
|
||||
if (type == AWSS_NOTIFY_DEV_RAND_SIGN) {
|
||||
topic_fmt = is_mcast ? TOPIC_AWSS_GETDEVICEINFO_MCAST : TOPIC_AWSS_GETDEVICEINFO_UCAST;
|
||||
} else if (type == AWSS_NOTIFY_SUCCESS) {
|
||||
topic_fmt = is_mcast ? TOPIC_AWSS_GET_CONNECTAP_INFO_MCAST : TOPIC_AWSS_GET_CONNECTAP_INFO_UCAST;
|
||||
} else {
|
||||
goto DEV_INFO_ERR;
|
||||
}
|
||||
awss_build_dev_info(type, buf, DEV_INFO_LEN_MAX);
|
||||
HAL_Snprintf(dev_info, DEV_INFO_LEN_MAX - 1, "{%s}", buf);
|
||||
|
||||
memset(buf, 0x00, DEV_INFO_LEN_MAX);
|
||||
HAL_Snprintf(buf, DEV_INFO_LEN_MAX - 1, AWSS_ACK_FMT, req_msg_id, 200, dev_info);
|
||||
|
||||
HAL_Free(dev_info);
|
||||
|
||||
awss_info("tx msg to app: %s", buf);
|
||||
|
||||
awss_build_topic(topic_fmt, topic, TOPIC_LEN_MAX);
|
||||
|
||||
if (0 != awss_cmp_coap_send_resp(buf, strlen(buf), remote, topic, request, NULL, NULL, 0)) {
|
||||
awss_err("tx dev info rsp fail.");
|
||||
}
|
||||
|
||||
HAL_Free(buf);
|
||||
return 0;
|
||||
|
||||
DEV_INFO_ERR:
|
||||
if (buf) {
|
||||
HAL_Free(buf);
|
||||
}
|
||||
if (dev_info) {
|
||||
HAL_Free(dev_info);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int awss_process_mcast_get_connectap_info(void *ctx, void *resource, void *remote, void *request)
|
||||
{
|
||||
if (g_awss_connectap_info_avaliable == 0) {
|
||||
return -1;
|
||||
}
|
||||
return process_get_device_info(ctx, resource, remote, request, 1, AWSS_NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
int awss_process_ucast_get_connectap_info(void *ctx, void *resource, void *remote, void *request)
|
||||
{
|
||||
if (g_awss_connectap_info_avaliable == 0) {
|
||||
return -1;
|
||||
}
|
||||
return process_get_device_info(ctx, resource, remote, request, 0, AWSS_NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_INFO_H__
|
||||
#define __AWSS_INFO_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int process_get_device_info(void *ctx, void *resource, void *remote, void *request, char is_mcast, int type);
|
||||
int awss_process_mcast_get_connectap_info(void *ctx, void *resource, void *remote, void *request);
|
||||
int awss_process_ucast_get_connectap_info(void *ctx, void *resource, void *remote, void *request);
|
||||
|
||||
int awss_stop_connectap_monitor();
|
||||
int awss_start_connectap_monitor();
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_LOG_H__
|
||||
#define __AWSS_LOG_H__
|
||||
|
||||
#include "infra_log.h"
|
||||
|
||||
#define awss_flow(...) log_flow("awss", __VA_ARGS__)
|
||||
#define awss_debug(...) log_debug("awss", __VA_ARGS__)
|
||||
#define awss_info(...) log_info("awss", __VA_ARGS__)
|
||||
#define awss_warn(...) log_warning("awss", __VA_ARGS__)
|
||||
#define awss_err(...) log_err("awss", __VA_ARGS__)
|
||||
#define awss_crit(...) log_crit("awss", __VA_ARGS__)
|
||||
#define awss_emerg(...) log_emerg("awss", __VA_ARGS__)
|
||||
#define awss_trace(...) log_crit("awss", __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,680 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AWSS_CHECK_RESP_TIME (300)
|
||||
#define AWSS_NOTIFY_PORT (5683)
|
||||
#define AWSS_NOTIFY_HOST "255.255.255.255"
|
||||
#define AWSS_DEV_NOTIFY_FMT "{\"id\":\"%u\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":{%s}}"
|
||||
|
||||
struct notify_map_t {
|
||||
uint8_t notify_type;
|
||||
char *notify_method;
|
||||
char *notify_topic;
|
||||
void *cb;
|
||||
};
|
||||
|
||||
static uint8_t g_notify_id;
|
||||
static char awss_notify_resp[AWSS_NOTIFY_TYPE_MAX] = {0};
|
||||
static uint16_t g_notify_msg_id[AWSS_NOTIFY_TYPE_MAX] = {0};
|
||||
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
static void *success_notify_timer = NULL;
|
||||
static void *devinfo_notify_timer = NULL;
|
||||
static void *success_notify_mutex = NULL;
|
||||
static void *devinfo_notify_mutex = NULL;
|
||||
#endif
|
||||
static void *dev_bind_notify_timer = NULL;
|
||||
static void *get_devinfo_timer = NULL;
|
||||
static void *dev_bind_notify_mutex = NULL;
|
||||
|
||||
extern char awss_report_token_suc;
|
||||
extern char awss_report_token_cnt;
|
||||
|
||||
static int awss_dev_bind_notify_resp(void *context, int result,
|
||||
void *userdata, void *remote,
|
||||
void *message);
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
static int awss_devinfo_notify_resp(void *context, int result,
|
||||
void *userdata, void *remote,
|
||||
void *message);
|
||||
static int awss_suc_notify_resp(void *context, int result,
|
||||
void *userdata, void *remote,
|
||||
void *message);
|
||||
int awss_devinfo_notify();
|
||||
int awss_suc_notify();
|
||||
#endif
|
||||
static int awss_notify_response(int type, int result, void *message);
|
||||
static int awss_process_get_devinfo();
|
||||
int awss_dev_bind_notify();
|
||||
|
||||
static const struct notify_map_t notify_map[] = {
|
||||
{AWSS_NOTIFY_DEV_BIND_TOKEN, METHOD_DEV_INFO_NOTIFY, TOPIC_NOTIFY, awss_dev_bind_notify_resp},
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
{AWSS_NOTIFY_DEV_RAND_SIGN, METHOD_AWSS_DEV_INFO_NOTIFY, TOPIC_AWSS_NOTIFY, awss_devinfo_notify_resp},
|
||||
{AWSS_NOTIFY_SUCCESS, METHOD_AWSS_CONNECTAP_NOTIFY, TOPIC_AWSS_CONNECTAP_NOTIFY, awss_suc_notify_resp}
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* {
|
||||
* "id": "123",
|
||||
* "code": 200,
|
||||
* "data": {}
|
||||
* }
|
||||
*/
|
||||
static int awss_dev_bind_notify_resp(void *context, int result,
|
||||
void *userdata, void *remote,
|
||||
void *message)
|
||||
{
|
||||
int res = awss_notify_response(AWSS_NOTIFY_DEV_BIND_TOKEN, result, message);
|
||||
if (res == 1) {
|
||||
awss_update_token();
|
||||
#ifdef DEV_BIND_TEST
|
||||
HAL_Reboot();
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
static int awss_devinfo_notify_resp(void *context, int result,
|
||||
void *userdata, void *remote,
|
||||
void *message)
|
||||
{
|
||||
return awss_notify_response(AWSS_NOTIFY_DEV_RAND_SIGN, result, message);
|
||||
}
|
||||
|
||||
static int awss_suc_notify_resp(void *context, int result,
|
||||
void *userdata, void *remote,
|
||||
void *message)
|
||||
{
|
||||
return awss_notify_response(AWSS_NOTIFY_SUCCESS, result, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int awss_notify_response(int type, int result, void *message)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
awss_flow("%s, type:%d,result:%u\r\n", __func__, type, result);
|
||||
|
||||
if (message == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (awss_cmp_get_coap_code(message) >= 0x60) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
int val = 0;
|
||||
int len = 0, mlen = 0;
|
||||
char *payload = NULL, *elem = NULL;
|
||||
|
||||
if ((payload = awss_cmp_get_coap_payload(message, &len)) == NULL ||
|
||||
len > 0x40 || len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
awss_debug("payload:%s\r\n", payload);
|
||||
|
||||
elem = json_get_value_by_name(payload, len, AWSS_JSON_ID, &mlen, 0);
|
||||
if (elem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = atoi(elem);
|
||||
if (val != 123 && val > g_notify_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
elem = json_get_value_by_name(payload, len, AWSS_JSON_CODE, &mlen, 0);
|
||||
if (elem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = atoi(elem);
|
||||
if (val != 200) {
|
||||
return 0;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
for (i = 0; i < sizeof(notify_map) / sizeof(notify_map[0]); i ++) {
|
||||
if (notify_map[i].notify_type != type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
awss_notify_resp[type] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return awss_notify_resp[type];
|
||||
}
|
||||
|
||||
int awss_notify_dev_info(int type, int count)
|
||||
{
|
||||
char *buf = NULL;
|
||||
char *dev_info = NULL;
|
||||
int i;
|
||||
platform_netaddr_t notify_sa;
|
||||
memset(¬ify_sa, 0, sizeof(notify_sa));
|
||||
|
||||
do {
|
||||
void *cb = NULL;
|
||||
char *method = NULL, *topic = NULL;
|
||||
for (i = 0; i < sizeof(notify_map) / sizeof(notify_map[0]); i ++) {
|
||||
if (notify_map[i].notify_type != type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
method = notify_map[i].notify_method;
|
||||
topic = notify_map[i].notify_topic;
|
||||
cb = notify_map[i].cb;
|
||||
break;
|
||||
}
|
||||
if (method == NULL || topic == NULL) {
|
||||
awss_err("parametes invalid");
|
||||
break;
|
||||
}
|
||||
|
||||
buf = os_zalloc(DEV_INFO_LEN_MAX);
|
||||
dev_info = os_zalloc(DEV_INFO_LEN_MAX);
|
||||
if (buf == NULL || dev_info == NULL) {
|
||||
awss_err("alloc mem fail");
|
||||
break;
|
||||
}
|
||||
|
||||
memset(¬ify_sa, 0, sizeof(notify_sa));
|
||||
memcpy(notify_sa.host, AWSS_NOTIFY_HOST, strlen(AWSS_NOTIFY_HOST));
|
||||
notify_sa.port = AWSS_NOTIFY_PORT;
|
||||
|
||||
awss_build_dev_info(type, dev_info, DEV_INFO_LEN_MAX);
|
||||
|
||||
HAL_Snprintf(buf, DEV_INFO_LEN_MAX - 1, AWSS_DEV_NOTIFY_FMT, ++ g_notify_id, method, dev_info);
|
||||
|
||||
awss_info("topic:%s\n", topic);
|
||||
awss_debug("payload:%s\n", buf);
|
||||
for (i = 0; i < count; i ++) {
|
||||
int ret = awss_cmp_coap_send(buf, strlen(buf), ¬ify_sa, topic, cb, &g_notify_msg_id[type]);
|
||||
awss_info("send notify %s", ret == 0 ? "success" : "fail");
|
||||
if (count > 1) {
|
||||
HAL_SleepMs(200 + 100 * i);
|
||||
}
|
||||
|
||||
if (awss_notify_resp[type]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (buf) {
|
||||
HAL_Free(buf);
|
||||
}
|
||||
if (dev_info) {
|
||||
HAL_Free(dev_info);
|
||||
}
|
||||
|
||||
return awss_notify_resp[type];
|
||||
}
|
||||
|
||||
#define AWSS_NOTIFY_CNT_MAX (30)
|
||||
|
||||
static void *coap_session_ctx = NULL;
|
||||
|
||||
static int awss_process_get_devinfo()
|
||||
{
|
||||
char *buf = NULL;
|
||||
char *dev_info = NULL;
|
||||
|
||||
if (awss_report_token_suc == 0) {
|
||||
awss_debug("try to report token to cloud");
|
||||
HAL_Timer_Start(get_devinfo_timer, AWSS_CHECK_RESP_TIME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (coap_session_ctx == NULL) {
|
||||
awss_debug("no get req");
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
int len = 0, id_len = 0;
|
||||
char *msg = NULL, *id = NULL;
|
||||
char req_msg_id[MSG_REQ_ID_LEN];
|
||||
char topic[TOPIC_LEN_MAX] = { 0 };
|
||||
struct coap_session_ctx_t *ctx = (struct coap_session_ctx_t *)coap_session_ctx;
|
||||
|
||||
buf = os_zalloc(DEV_INFO_LEN_MAX);
|
||||
if (buf == NULL) {
|
||||
goto GET_DEV_INFO_ERR;
|
||||
}
|
||||
|
||||
dev_info = os_zalloc(DEV_INFO_LEN_MAX);
|
||||
if (dev_info == NULL) {
|
||||
goto GET_DEV_INFO_ERR;
|
||||
}
|
||||
|
||||
msg = awss_cmp_get_coap_payload(ctx->request, &len);
|
||||
if (msg == NULL) {
|
||||
goto GET_DEV_INFO_ERR;
|
||||
}
|
||||
|
||||
id = json_get_value_by_name(msg, len, "id", &id_len, 0);
|
||||
memset(req_msg_id, 0, sizeof(req_msg_id));
|
||||
memcpy(req_msg_id, id, id_len);
|
||||
|
||||
awss_build_dev_info(AWSS_NOTIFY_DEV_BIND_TOKEN, buf, DEV_INFO_LEN_MAX);
|
||||
HAL_Snprintf(dev_info, DEV_INFO_LEN_MAX - 1, "{%s}", buf);
|
||||
memset(buf, 0x00, DEV_INFO_LEN_MAX);
|
||||
HAL_Snprintf(buf, DEV_INFO_LEN_MAX - 1, AWSS_ACK_FMT, req_msg_id, 200, dev_info);
|
||||
HAL_Free(dev_info);
|
||||
|
||||
awss_info("sending message to app: %s", buf);
|
||||
if (ctx->is_mcast) {
|
||||
awss_build_topic((const char *)TOPIC_GETDEVICEINFO_MCAST, topic, TOPIC_LEN_MAX);
|
||||
} else {
|
||||
awss_build_topic((const char *)TOPIC_GETDEVICEINFO_UCAST, topic, TOPIC_LEN_MAX);
|
||||
}
|
||||
|
||||
/*before tx to app, clear token suc flag*/
|
||||
awss_update_token();
|
||||
|
||||
if (0 != awss_cmp_coap_send_resp(buf, strlen(buf), ctx->remote, topic, ctx->request, NULL, NULL, 0)) {
|
||||
awss_err("sending failed.");
|
||||
}
|
||||
|
||||
HAL_Free(buf);
|
||||
awss_release_coap_ctx(coap_session_ctx);
|
||||
coap_session_ctx = NULL;
|
||||
awss_stop_timer(get_devinfo_timer);
|
||||
get_devinfo_timer = NULL;
|
||||
} while (0);
|
||||
|
||||
return 0;
|
||||
|
||||
GET_DEV_INFO_ERR:
|
||||
awss_release_coap_ctx(coap_session_ctx);
|
||||
coap_session_ctx = NULL;
|
||||
awss_stop_timer(get_devinfo_timer);
|
||||
get_devinfo_timer = NULL;
|
||||
|
||||
if (buf) {
|
||||
HAL_Free(buf);
|
||||
}
|
||||
if (dev_info) {
|
||||
HAL_Free(dev_info);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int online_get_device_info(void *ctx, void *resource, void *remote,
|
||||
void *request, char is_mcast)
|
||||
{
|
||||
int timeout = 0;
|
||||
/*
|
||||
* if cloud is not ready, don't response token
|
||||
*/
|
||||
if (awss_report_token_cnt == 0) {
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* if the last one is not finished, drop current request
|
||||
*/
|
||||
if (coap_session_ctx != NULL) {
|
||||
awss_debug("no req");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* copy coap session context
|
||||
*/
|
||||
coap_session_ctx = awss_cpy_coap_ctx(request, remote, is_mcast);
|
||||
if (coap_session_ctx == NULL) {
|
||||
awss_err("cpy req ctx fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeout = awss_token_timeout();
|
||||
if (timeout) {
|
||||
produce_random(aes_random, sizeof(aes_random));
|
||||
awss_report_token();
|
||||
}
|
||||
|
||||
if (get_devinfo_timer == NULL) {
|
||||
get_devinfo_timer = HAL_Timer_Create("get_devinfo", (void (*)(void *))awss_process_get_devinfo, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(get_devinfo_timer);
|
||||
HAL_Timer_Start(get_devinfo_timer, timeout ? AWSS_CHECK_RESP_TIME : 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int online_mcast_get_device_info(void *ctx, void *resource, void *remote, void *request)
|
||||
{
|
||||
return online_get_device_info(ctx, resource, remote, request, 1);
|
||||
}
|
||||
|
||||
int online_ucast_get_device_info(void *ctx, void *resource, void *remote, void *request)
|
||||
{
|
||||
return online_get_device_info(ctx, resource, remote, request, 0);
|
||||
}
|
||||
|
||||
static int dev_bind_interval = 0;
|
||||
static char dev_bind_cnt = 0;
|
||||
static int __awss_dev_bind_notify()
|
||||
{
|
||||
/*
|
||||
* wait for token is sent to cloud and rx reply from cloud
|
||||
*/
|
||||
if (awss_report_token_suc == 0) {
|
||||
if (dev_bind_notify_timer == NULL) {
|
||||
dev_bind_notify_timer = HAL_Timer_Create("dev_bind", (void (*)(void *))__awss_dev_bind_notify, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(dev_bind_notify_timer);
|
||||
HAL_Timer_Start(dev_bind_notify_timer, AWSS_CHECK_RESP_TIME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev_bind_notify_mutex == NULL) {
|
||||
dev_bind_notify_mutex = HAL_MutexCreate();
|
||||
if (dev_bind_notify_mutex == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_bind_cnt == 0) {
|
||||
awss_event_post(IOTX_AWSS_BIND_NOTIFY);
|
||||
}
|
||||
|
||||
HAL_MutexLock(dev_bind_notify_mutex);
|
||||
|
||||
do {
|
||||
uint8_t i = 0;
|
||||
|
||||
if (awss_notify_resp[AWSS_NOTIFY_DEV_BIND_TOKEN] != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < RANDOM_MAX_LEN; i ++)
|
||||
if (aes_random[i] != 0x00) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= RANDOM_MAX_LEN) {
|
||||
produce_random(aes_random, sizeof(aes_random));
|
||||
}
|
||||
|
||||
if (awss_token_timeout() == 0) {
|
||||
awss_notify_dev_info(AWSS_NOTIFY_DEV_BIND_TOKEN, 1);
|
||||
dev_bind_interval += 100;
|
||||
dev_bind_cnt ++;
|
||||
}
|
||||
#ifdef DEV_BIND_TEST
|
||||
if (dev_bind_cnt > 3) {
|
||||
HAL_Reboot();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dev_bind_cnt < AWSS_NOTIFY_CNT_MAX &&
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_BIND_TOKEN] == 0) {
|
||||
if (dev_bind_notify_timer == NULL) {
|
||||
dev_bind_notify_timer = HAL_Timer_Create("dev_bind", (void (*)(void *))awss_dev_bind_notify, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(dev_bind_notify_timer);
|
||||
HAL_Timer_Start(dev_bind_notify_timer, dev_bind_interval);
|
||||
HAL_MutexUnlock(dev_bind_notify_mutex);
|
||||
return 0;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
awss_cmp_coap_cancel_packet(g_notify_msg_id[AWSS_NOTIFY_DEV_BIND_TOKEN]);
|
||||
g_notify_msg_id[AWSS_NOTIFY_DEV_BIND_TOKEN] = 0;
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_BIND_TOKEN] = 0;
|
||||
dev_bind_interval = 0;
|
||||
dev_bind_cnt = 0;
|
||||
if (dev_bind_notify_timer) {
|
||||
awss_stop_timer(dev_bind_notify_timer);
|
||||
dev_bind_notify_timer = NULL;
|
||||
}
|
||||
if (dev_bind_notify_mutex) {
|
||||
HAL_MutexUnlock(dev_bind_notify_mutex);
|
||||
HAL_MutexDestroy(dev_bind_notify_mutex);
|
||||
dev_bind_notify_mutex = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int awss_dev_bind_notify()
|
||||
{
|
||||
dev_bind_cnt = 0;
|
||||
dev_bind_interval = 0;
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_BIND_TOKEN] = 0;
|
||||
|
||||
return __awss_dev_bind_notify();
|
||||
}
|
||||
|
||||
int awss_dev_bind_notify_stop()
|
||||
{
|
||||
if (dev_bind_notify_mutex) {
|
||||
HAL_MutexLock(dev_bind_notify_mutex);
|
||||
}
|
||||
|
||||
do {
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_BIND_TOKEN] = 1;
|
||||
dev_bind_cnt = AWSS_NOTIFY_CNT_MAX;
|
||||
if (dev_bind_notify_timer == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
awss_stop_timer(dev_bind_notify_timer);
|
||||
dev_bind_notify_timer = NULL;
|
||||
} while (0);
|
||||
|
||||
awss_cmp_coap_cancel_packet(g_notify_msg_id[AWSS_NOTIFY_DEV_BIND_TOKEN]);
|
||||
g_notify_msg_id[AWSS_NOTIFY_DEV_BIND_TOKEN] = 0;
|
||||
|
||||
if (dev_bind_notify_mutex) {
|
||||
HAL_MutexUnlock(dev_bind_notify_mutex);
|
||||
HAL_MutexDestroy(dev_bind_notify_mutex);
|
||||
dev_bind_notify_mutex = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
static int suc_interval = 0;
|
||||
static char suc_cnt = 0;
|
||||
static int __awss_suc_notify()
|
||||
{
|
||||
awss_debug("resp:%d\r\n", awss_notify_resp[AWSS_NOTIFY_SUCCESS]);
|
||||
|
||||
if (success_notify_mutex == NULL) {
|
||||
success_notify_mutex = HAL_MutexCreate();
|
||||
if (success_notify_mutex == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (suc_cnt == 0) {
|
||||
awss_event_post(IOTX_AWSS_SUC_NOTIFY);
|
||||
}
|
||||
|
||||
HAL_MutexLock(success_notify_mutex);
|
||||
|
||||
do {
|
||||
if (awss_notify_resp[AWSS_NOTIFY_SUCCESS] != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
awss_notify_dev_info(AWSS_NOTIFY_SUCCESS, 1);
|
||||
|
||||
suc_interval += 100;
|
||||
if (suc_cnt ++ < AWSS_NOTIFY_CNT_MAX &&
|
||||
awss_notify_resp[AWSS_NOTIFY_SUCCESS] == 0) {
|
||||
if (success_notify_timer == NULL) {
|
||||
success_notify_timer = HAL_Timer_Create("awss_suc", (void (*)(void *))__awss_suc_notify, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(success_notify_timer);
|
||||
HAL_Timer_Start(success_notify_timer, suc_interval);
|
||||
HAL_MutexUnlock(success_notify_mutex);
|
||||
return 0;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
awss_cmp_coap_cancel_packet(g_notify_msg_id[AWSS_NOTIFY_SUCCESS]);
|
||||
g_notify_msg_id[AWSS_NOTIFY_SUCCESS] = 0;
|
||||
|
||||
awss_notify_resp[AWSS_NOTIFY_SUCCESS] = 0;
|
||||
suc_interval = 0;
|
||||
suc_cnt = 0;
|
||||
if (success_notify_timer) {
|
||||
awss_stop_timer(success_notify_timer);
|
||||
success_notify_timer = NULL;
|
||||
}
|
||||
|
||||
if (success_notify_mutex) {
|
||||
HAL_MutexUnlock(success_notify_mutex);
|
||||
HAL_MutexDestroy(success_notify_mutex);
|
||||
success_notify_mutex = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int awss_suc_notify()
|
||||
{
|
||||
suc_cnt = 0;
|
||||
suc_interval = 0;
|
||||
awss_notify_resp[AWSS_NOTIFY_SUCCESS] = 0;
|
||||
return __awss_suc_notify();
|
||||
}
|
||||
|
||||
int awss_suc_notify_stop()
|
||||
{
|
||||
if (success_notify_mutex) {
|
||||
HAL_MutexLock(success_notify_mutex);
|
||||
}
|
||||
|
||||
do {
|
||||
awss_notify_resp[AWSS_NOTIFY_SUCCESS] = 1;
|
||||
suc_cnt = AWSS_NOTIFY_CNT_MAX;
|
||||
if (success_notify_timer == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
awss_stop_timer(success_notify_timer);
|
||||
success_notify_timer = NULL;
|
||||
} while (0);
|
||||
|
||||
awss_cmp_coap_cancel_packet(g_notify_msg_id[AWSS_NOTIFY_SUCCESS]);
|
||||
g_notify_msg_id[AWSS_NOTIFY_SUCCESS] = 0;
|
||||
|
||||
if (success_notify_mutex) {
|
||||
HAL_MutexUnlock(success_notify_mutex);
|
||||
HAL_MutexDestroy(success_notify_mutex);
|
||||
success_notify_mutex = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int devinfo_interval = 0;
|
||||
static char devinfo_cnt = 0;
|
||||
static int __awss_devinfo_notify()
|
||||
{
|
||||
if (devinfo_notify_mutex == NULL) {
|
||||
devinfo_notify_mutex = HAL_MutexCreate();
|
||||
if (devinfo_notify_mutex == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
HAL_MutexLock(devinfo_notify_mutex);
|
||||
|
||||
do {
|
||||
if (awss_notify_resp[AWSS_NOTIFY_DEV_RAND_SIGN] != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
awss_notify_dev_info(AWSS_NOTIFY_DEV_RAND_SIGN, 1);
|
||||
|
||||
devinfo_interval += 100;
|
||||
if (devinfo_cnt ++ < AWSS_NOTIFY_CNT_MAX &&
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_RAND_SIGN] == 0) {
|
||||
if (devinfo_notify_timer == NULL) {
|
||||
devinfo_notify_timer = HAL_Timer_Create("devinfo", (void (*)(void *))__awss_devinfo_notify, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(devinfo_notify_timer);
|
||||
HAL_Timer_Start(devinfo_notify_timer, devinfo_interval);
|
||||
HAL_MutexUnlock(devinfo_notify_mutex);
|
||||
return 0;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
awss_cmp_coap_cancel_packet(g_notify_msg_id[AWSS_NOTIFY_DEV_RAND_SIGN]);
|
||||
g_notify_msg_id[AWSS_NOTIFY_DEV_RAND_SIGN] = 0;
|
||||
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_RAND_SIGN] = 0;
|
||||
devinfo_interval = 0;
|
||||
devinfo_cnt = 0;
|
||||
if (devinfo_notify_timer) {
|
||||
awss_stop_timer(devinfo_notify_timer);
|
||||
devinfo_notify_timer = NULL;
|
||||
}
|
||||
if (devinfo_notify_mutex) {
|
||||
HAL_MutexUnlock(devinfo_notify_mutex);
|
||||
HAL_MutexDestroy(devinfo_notify_mutex);
|
||||
devinfo_notify_mutex = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int awss_devinfo_notify()
|
||||
{
|
||||
devinfo_cnt = 0;
|
||||
devinfo_interval = 0;
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_RAND_SIGN] = 0;
|
||||
return __awss_devinfo_notify();
|
||||
}
|
||||
|
||||
int awss_devinfo_notify_stop()
|
||||
{
|
||||
if (devinfo_notify_mutex) {
|
||||
HAL_MutexLock(devinfo_notify_mutex);
|
||||
}
|
||||
|
||||
do {
|
||||
awss_notify_resp[AWSS_NOTIFY_DEV_RAND_SIGN] = 1;
|
||||
devinfo_cnt = AWSS_NOTIFY_CNT_MAX;
|
||||
if (devinfo_notify_timer == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
awss_stop_timer(devinfo_notify_timer);
|
||||
devinfo_notify_timer = NULL;
|
||||
} while (0);
|
||||
|
||||
awss_cmp_coap_cancel_packet(g_notify_msg_id[AWSS_NOTIFY_DEV_RAND_SIGN]);
|
||||
g_notify_msg_id[AWSS_NOTIFY_DEV_RAND_SIGN] = 0;
|
||||
|
||||
if (devinfo_notify_mutex) {
|
||||
HAL_MutexUnlock(devinfo_notify_mutex);
|
||||
HAL_MutexDestroy(devinfo_notify_mutex);
|
||||
devinfo_notify_mutex = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_NOTIFY_H__
|
||||
#define __AWSS_NOTIFY_H__
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
enum {
|
||||
AWSS_NOTIFY_DEV_INFO = 0,
|
||||
AWSS_NOTIFY_DEV_BIND_TOKEN,
|
||||
AWSS_NOTIFY_DEV_RAND_SIGN,
|
||||
AWSS_NOTIFY_SUCCESS,
|
||||
AWSS_NOTIFY_TYPE_MAX,
|
||||
};
|
||||
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
int awss_suc_notify();
|
||||
int awss_devinfo_notify();
|
||||
int awss_suc_notify_stop();
|
||||
int awss_devinfo_notify_stop();
|
||||
#endif
|
||||
|
||||
int awss_dev_bind_notify();
|
||||
int awss_dev_bind_notify_stop();
|
||||
int awss_notify_dev_info(int type, int count);
|
||||
int online_mcast_get_device_info(void *ctx, void *resource, void *remote, void *request);
|
||||
int online_ucast_get_device_info(void *ctx, void *resource, void *remote, void *request);
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#define AWSS_DEV_RAND_SIGN_FMT ",\"random\":\"%s\",\"signMethod\":%d,\"sign\":\"%s\""
|
||||
#define AWSS_DEV_BIND_TOKEN_FMT ",\"token\":\"%s\",\"remainTime\":%d,\"type\":%d"
|
||||
#define AWSS_SUCCESS_FMT ",\"type\":%d"
|
||||
#define AWSS_DEV_INFO_FMT "\"awssVer\":%s,\"productKey\":\"%s\",\"deviceName\":\"%s\",\"mac\":\"%s\",\"ip\":\"%s\",\"cipherType\":%d"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int bind_get_encrypt_type()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
static void *awss_get_dev_info(void *dev_info, int len)
|
||||
{
|
||||
char dev_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char mac_str[HAL_MAC_LEN + 1] = {0};
|
||||
char pk[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char ip_str[OS_IP_LEN + 1] = {0};
|
||||
|
||||
if (dev_info == NULL || len <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HAL_GetProductKey(pk);
|
||||
HAL_GetDeviceName(dev_name);
|
||||
os_wifi_get_mac_str(mac_str);
|
||||
HAL_Wifi_Get_IP(ip_str, NULL);
|
||||
#if 0
|
||||
awss_dict_crypt(NOTIFY_ENCODE_TABLE, (uint8_t *)pk, strlen(pk));
|
||||
awss_dict_crypt(NOTIFY_ENCODE_TABLE, (uint8_t *)dev_name, strlen(dev_name));
|
||||
#endif
|
||||
HAL_Snprintf(dev_info, len - 1, AWSS_DEV_INFO_FMT, AWSS_VER, pk, dev_name, mac_str, ip_str,
|
||||
bind_get_encrypt_type());
|
||||
|
||||
return dev_info;
|
||||
}
|
||||
|
||||
void *awss_build_dev_info(int type, void *dev_info, int info_len)
|
||||
{
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
if (dev_info == NULL || info_len <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = os_zalloc(DEV_INFO_LEN_MAX);
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len += HAL_Snprintf((char *)dev_info + len, info_len - len - 1, "%s", (char *)awss_get_dev_info(buf, DEV_INFO_LEN_MAX));
|
||||
HAL_Free(buf);
|
||||
buf = NULL;
|
||||
|
||||
switch (type) {
|
||||
case AWSS_NOTIFY_DEV_BIND_TOKEN: {
|
||||
char rand_str[(RANDOM_MAX_LEN << 1) + 1] = {0};
|
||||
utils_hex_to_str(aes_random, RANDOM_MAX_LEN, rand_str, sizeof(rand_str));
|
||||
len += HAL_Snprintf((char *)dev_info + len, info_len - len - 1, AWSS_DEV_BIND_TOKEN_FMT, rand_str,
|
||||
awss_token_remain_time(), 0);
|
||||
break;
|
||||
}
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
case AWSS_NOTIFY_SUCCESS: {
|
||||
len += HAL_Snprintf((char *)dev_info + len, info_len - len - 1, AWSS_SUCCESS_FMT, 0);
|
||||
break;
|
||||
}
|
||||
case AWSS_NOTIFY_DEV_RAND_SIGN: {
|
||||
char sign_str[DEV_SIGN_SIZE * 2 + 1] = {0};
|
||||
char rand_str[(RANDOM_MAX_LEN << 1) + 1] = {0};
|
||||
{
|
||||
int txt_len = 80;
|
||||
char txt[80] = {0};
|
||||
char key[IOTX_DEVICE_SECRET_LEN + 1] = {0};
|
||||
uint8_t sign[DEV_SIGN_SIZE + 1] = {0};
|
||||
|
||||
if (bind_get_encrypt_type() == 3) { /* aes-key per product */
|
||||
HAL_GetProductSecret(key);
|
||||
} else { /* aes-key per device */
|
||||
HAL_GetDeviceSecret(key);
|
||||
}
|
||||
awss_build_sign_src(txt, &txt_len);
|
||||
produce_signature(sign, (uint8_t *)txt, txt_len, key);
|
||||
utils_hex_to_str(sign, DEV_SIGN_SIZE, sign_str, sizeof(sign_str));
|
||||
}
|
||||
utils_hex_to_str(aes_random, RANDOM_MAX_LEN, rand_str, sizeof(rand_str));
|
||||
len += HAL_Snprintf((char *)dev_info + len, info_len - len - 1, AWSS_DEV_RAND_SIGN_FMT, rand_str, 0, sign_str);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return dev_info;
|
||||
}
|
||||
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
char *awss_build_sign_src(char *sign_src, int *sign_src_len)
|
||||
{
|
||||
char *pk = NULL, *dev_name = NULL;
|
||||
int dev_name_len, pk_len, text_len;
|
||||
|
||||
if (sign_src == NULL || sign_src_len == NULL) {
|
||||
goto build_sign_src_err;
|
||||
}
|
||||
|
||||
pk = os_zalloc(IOTX_PRODUCT_KEY_LEN + 1);
|
||||
dev_name = os_zalloc(IOTX_DEVICE_NAME_LEN + 1);
|
||||
if (pk == NULL || dev_name == NULL) {
|
||||
goto build_sign_src_err;
|
||||
}
|
||||
|
||||
HAL_GetProductKey(pk);
|
||||
HAL_GetDeviceName(dev_name);
|
||||
|
||||
pk_len = strlen(pk);
|
||||
dev_name_len = strlen(dev_name);
|
||||
|
||||
text_len = RANDOM_MAX_LEN + dev_name_len + pk_len;
|
||||
if (*sign_src_len < text_len) {
|
||||
goto build_sign_src_err;
|
||||
}
|
||||
|
||||
*sign_src_len = text_len;
|
||||
|
||||
memcpy(sign_src, aes_random, RANDOM_MAX_LEN);
|
||||
memcpy(sign_src + RANDOM_MAX_LEN, dev_name, dev_name_len);
|
||||
memcpy(sign_src + RANDOM_MAX_LEN + dev_name_len, pk, pk_len);
|
||||
|
||||
HAL_Free(pk);
|
||||
HAL_Free(dev_name);
|
||||
|
||||
return sign_src;
|
||||
|
||||
build_sign_src_err:
|
||||
if (pk) {
|
||||
HAL_Free(pk);
|
||||
}
|
||||
if (dev_name) {
|
||||
HAL_Free(dev_name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
const char *awss_build_topic(const char *topic_fmt, char *topic, uint32_t tlen)
|
||||
{
|
||||
char pk[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char dev_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
if (topic == NULL || topic_fmt == NULL || tlen == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HAL_GetProductKey(pk);
|
||||
HAL_GetDeviceName(dev_name);
|
||||
|
||||
HAL_Snprintf(topic, tlen - 1, topic_fmt, pk, dev_name);
|
||||
|
||||
return topic;
|
||||
}
|
||||
|
||||
int awss_build_packet(int type, void *id, void *ver, void *method, void *data, int code, void *packet, int *packet_len)
|
||||
{
|
||||
int len;
|
||||
if (packet_len == NULL || data == NULL || packet == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = *packet_len;
|
||||
if (len <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (type == AWSS_CMP_PKT_TYPE_REQ) {
|
||||
if (ver == NULL || method == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = HAL_Snprintf(packet, len - 1, AWSS_REQ_FMT, (char *)id, (char *)ver, (char *)method, (char *)data);
|
||||
return 0;
|
||||
} else if (type == AWSS_CMP_PKT_TYPE_RSP) {
|
||||
len = HAL_Snprintf(packet, len - 1, AWSS_ACK_FMT, (char *)id, code, (char *)data);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void produce_random(uint8_t *random, uint32_t len)
|
||||
{
|
||||
int i = 0;
|
||||
int time = HAL_UptimeMs();
|
||||
HAL_Srandom(time);
|
||||
for (i = 0; i < len; i ++) {
|
||||
random[i] = HAL_Random(0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_PACKET_H__
|
||||
#define __AWSS_PACKET_H__
|
||||
#include "infra_sha1.h"
|
||||
|
||||
#define MSG_REQ_ID_LEN (16)
|
||||
#define TOPIC_LEN_MAX (128)
|
||||
#define DEV_INFO_LEN_MAX (512)
|
||||
#define DEV_SIGN_SIZE (SHA1_DIGEST_SIZE)
|
||||
|
||||
#define ILOP_VER "1.0"
|
||||
#define AWSS_VER "{\"smartconfig\":\"2.0\",\"zconfig\":\"2.0\",\"router\":\"2.0\",\"ap\":\"2.0\",\"softap\":\"2.0\"}"
|
||||
|
||||
#define TOPIC_AWSS_WIFILIST "/sys/%s/%s/awss/event/wifilist/get"
|
||||
#define TOPIC_AWSS_SWITCHAP "/sys/%s/%s/awss/device/switchap"
|
||||
#define TOPIC_AWSS_GETDEVICEINFO_MCAST "/sys/awss/device/info/get"
|
||||
#define TOPIC_AWSS_GETDEVICEINFO_UCAST "/sys/%s/%s/awss/device/info/get"
|
||||
#define TOPIC_AWSS_GET_CONNECTAP_INFO_MCAST "/sys/awss/device/connectap/info/get"
|
||||
#define TOPIC_AWSS_GET_CONNECTAP_INFO_UCAST "/sys/%s/%s/awss/device/connectap/info/get"
|
||||
#define TOPIC_GETDEVICEINFO_MCAST "/sys/device/info/get"
|
||||
#define TOPIC_GETDEVICEINFO_UCAST "/sys/%s/%s/device/info/get"
|
||||
#define TOPIC_POST_STATIS "/sys/%s/%s/thing/log/post"
|
||||
#define TOPIC_AWSS_NOTIFY "/sys/awss/device/info/notify"
|
||||
#define TOPIC_AWSS_CONNECTAP_NOTIFY "/sys/awss/event/connectap/notify"
|
||||
#define TOPIC_NOTIFY "/sys/device/info/notify"
|
||||
#define TOPIC_SWITCHAP "/sys/%s/%s/thing/awss/device/switchap"
|
||||
#define TOPIC_SWITCHAP_REPLY "/sys/%s/%s/thing/awss/device/switchap_reply"
|
||||
#define TOPIC_ZC_ENROLLEE "/sys/%s/%s/thing/awss/enrollee/found"
|
||||
#define TOPIC_ZC_ENROLLEE_REPLY "/sys/%s/%s/thing/awss/enrollee/found_reply"
|
||||
#define TOPIC_ZC_CHECKIN "/sys/%s/%s/thing/awss/enrollee/checkin"
|
||||
#define TOPIC_ZC_CHECKIN_REPLY "/sys/%s/%s/thing/awss/enrollee/checkin_reply"
|
||||
#define TOPIC_ZC_CIPHER "/sys/%s/%s/thing/cipher/get"
|
||||
#define TOPIC_ZC_CIPHER_REPLY "/sys/%s/%s/thing/cipher/get_reply"
|
||||
#define TOPIC_MATCH_REPORT "/sys/%s/%s/thing/awss/enrollee/match"
|
||||
#define TOPIC_MATCH_REPORT_REPLY "/sys/%s/%s/thing/awss/enrollee/match_reply"
|
||||
#define TOPIC_AWSS_DEV_AP_SWITCHAP "/sys/awss/device/softap/switchap"
|
||||
|
||||
#define METHOD_DEV_INFO_NOTIFY "device.info.notify"
|
||||
#define METHOD_AWSS_DEV_INFO_NOTIFY "awss.device.info.notify"
|
||||
#define METHOD_AWSS_CONNECTAP_NOTIFY "awss.event.connectap.notify"
|
||||
#define METHOD_AWSS_DEV_AP_SWITCHAP "awss.device.softap.switchap"
|
||||
#define METHOD_EVENT_ZC_SWITCHAP "thing.awss.device.switchap"
|
||||
#define METHOD_EVENT_ZC_ENROLLEE "thing.awss.enrollee.found"
|
||||
#define METHOD_EVENT_ZC_CHECKIN "thing.awss.enrollee.checkin"
|
||||
#define METHOD_EVENT_ZC_CIPHER "thing.cipher.get"
|
||||
#define METHOD_MATCH_REPORT "thing.awss.enrollee.match"
|
||||
#define METHOD_LOG_POST "things.log.post"
|
||||
|
||||
#define AWSS_ACK_FMT "{\"id\":%s,\"code\":%d,\"data\":%s}"
|
||||
#define AWSS_REQ_FMT "{\"id\":%s,\"version\":\"%s\",\"method\":\"%s\",\"params\":%s}"
|
||||
#define AWSS_JSON_PARAM "params"
|
||||
#define AWSS_JSON_CODE "code"
|
||||
#define AWSS_JSON_ID "id"
|
||||
#define AWSS_STATIS_FMT "{\"template\":\"timestamp logLevel module traceContext logContent\",\"contents\":[\"%u %s %s %u %s\"]}"
|
||||
|
||||
enum {
|
||||
AWSS_CMP_PKT_TYPE_REQ = 1,
|
||||
AWSS_CMP_PKT_TYPE_RSP,
|
||||
};
|
||||
|
||||
void produce_random(uint8_t *random, uint32_t len);
|
||||
char *awss_build_sign_src(char *sign_src, int *sign_src_len);
|
||||
void *awss_build_dev_info(int type, void *dev_info, int info_len);
|
||||
const char *awss_build_topic(const char *topic_fmt, char *topic, uint32_t tlen);
|
||||
int awss_build_packet(int type, void *id, void *ver, void *method, void *data, int code, void *pkt, int *pkt_len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AWSS_REPORT_LEN_MAX (256)
|
||||
#define AWSS_TOKEN_TIMEOUT_MS (45 * 1000)
|
||||
#define MATCH_MONITOR_TIMEOUT_MS (10 * 1000)
|
||||
#define MATCH_REPORT_CNT_MAX (2)
|
||||
|
||||
volatile char awss_report_token_suc = 0;
|
||||
volatile char awss_report_token_cnt = 0;
|
||||
static char awss_report_id = 0;
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
static uint8_t switchap_bssid[ETH_ALEN] = {0};
|
||||
static char switchap_ssid[OS_MAX_SSID_LEN] = {0};
|
||||
static char switchap_passwd[OS_MAX_PASSWD_LEN] = {0};
|
||||
static void *switchap_timer = NULL;
|
||||
#endif
|
||||
|
||||
static uint32_t awss_report_token_time = 0;
|
||||
static void *report_token_timer = NULL;
|
||||
|
||||
static int awss_report_token_to_cloud();
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
static int awss_switch_ap_online();
|
||||
static int awss_reboot_system();
|
||||
#endif
|
||||
|
||||
int awss_token_remain_time()
|
||||
{
|
||||
int remain = 0;
|
||||
uint32_t cur = os_get_time_ms();
|
||||
uint32_t diff = (uint32_t)(cur - awss_report_token_time);
|
||||
|
||||
if (awss_report_token_suc == 0) {
|
||||
return remain;
|
||||
}
|
||||
|
||||
if (diff < AWSS_TOKEN_TIMEOUT_MS) {
|
||||
remain = AWSS_TOKEN_TIMEOUT_MS - diff;
|
||||
}
|
||||
|
||||
return remain;
|
||||
}
|
||||
|
||||
int awss_update_token()
|
||||
{
|
||||
awss_report_token_time = 0;
|
||||
awss_report_token_cnt = 0;
|
||||
awss_report_token_suc = 0;
|
||||
|
||||
if (report_token_timer == NULL) {
|
||||
report_token_timer = HAL_Timer_Create("rp_token", (void (*)(void *))awss_report_token_to_cloud, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(report_token_timer);
|
||||
HAL_Timer_Start(report_token_timer, 10);
|
||||
awss_info("update token");
|
||||
|
||||
produce_random(aes_random, sizeof(aes_random));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_token_timeout()
|
||||
{
|
||||
uint32_t cur;
|
||||
if (awss_report_token_time == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
cur = os_get_time_ms();
|
||||
if ((uint32_t)(cur - awss_report_token_time) > AWSS_TOKEN_TIMEOUT_MS) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void awss_report_token_reply(void *pcontext, void *pclient, void *msg)
|
||||
{
|
||||
int ret, len;
|
||||
char *payload;
|
||||
char *id = NULL;
|
||||
char reply_id = 0;
|
||||
uint32_t payload_len;
|
||||
|
||||
ret = awss_cmp_mqtt_get_payload(msg, &payload, &payload_len);
|
||||
|
||||
if (ret != 0 || payload == NULL || payload_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
id = json_get_value_by_name(payload, payload_len, AWSS_JSON_ID, &len, NULL);
|
||||
if (id == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
reply_id = atoi(id);
|
||||
if (reply_id + 1 < awss_report_id) {
|
||||
return;
|
||||
}
|
||||
awss_info("%s\r\n", __func__);
|
||||
awss_report_token_suc = 1;
|
||||
awss_stop_timer(report_token_timer);
|
||||
report_token_timer = NULL;
|
||||
AWSS_DB_UPDATE_STATIS(AWSS_DB_STATIS_SUC);
|
||||
AWSS_DB_DISP_STATIS();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
void awss_online_switchap(void *pcontext, void *pclient, void *msg)
|
||||
{
|
||||
#define SWITCHAP_RSP_LEN (64)
|
||||
#define AWSS_BSSID_STR_LEN (17)
|
||||
#define AWSS_SSID "ssid"
|
||||
#define AWSS_PASSWD "passwd"
|
||||
#define AWSS_BSSID "bssid"
|
||||
#define AWSS_SWITCH_MODE "switchMode"
|
||||
#define AWSS_TIMEOUT "timeout"
|
||||
|
||||
int len = 0, timeout = 0;
|
||||
char *packet = NULL, *awss_info = NULL, *elem = NULL;
|
||||
int packet_len = SWITCHAP_RSP_LEN, awss_info_len = 0;
|
||||
|
||||
uint32_t payload_len;
|
||||
char *payload;
|
||||
int ret;
|
||||
|
||||
ret = awss_cmp_mqtt_get_payload(msg, &payload, &payload_len);
|
||||
|
||||
if (ret != 0) {
|
||||
goto ONLINE_SWITCHAP_FAIL;
|
||||
}
|
||||
|
||||
if (payload == NULL || payload_len == 0) {
|
||||
goto ONLINE_SWITCHAP_FAIL;
|
||||
}
|
||||
|
||||
awss_debug("online switchap len:%u, payload:%s\r\n", payload_len, payload);
|
||||
packet = os_zalloc(packet_len + 1);
|
||||
if (packet == NULL) {
|
||||
goto ONLINE_SWITCHAP_FAIL;
|
||||
}
|
||||
|
||||
awss_info = json_get_value_by_name(payload, payload_len, AWSS_JSON_PARAM, &awss_info_len, NULL);
|
||||
if (awss_info == NULL || awss_info_len == 0) {
|
||||
goto ONLINE_SWITCHAP_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* get SSID , PASSWD, BSSID of router
|
||||
*/
|
||||
elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_SSID, &len, NULL);
|
||||
if (elem == NULL || len <= 0 || len >= OS_MAX_SSID_LEN) {
|
||||
goto ONLINE_SWITCHAP_FAIL;
|
||||
}
|
||||
|
||||
memset(switchap_ssid, 0, sizeof(switchap_ssid));
|
||||
memcpy(switchap_ssid, elem, len);
|
||||
|
||||
len = 0;
|
||||
elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_PASSWD, &len, NULL);
|
||||
if (elem == NULL || len <= 0 || len >= OS_MAX_PASSWD_LEN) {
|
||||
goto ONLINE_SWITCHAP_FAIL;
|
||||
}
|
||||
|
||||
memset(switchap_passwd, 0, sizeof(switchap_passwd));
|
||||
memcpy(switchap_passwd, elem, len);
|
||||
|
||||
len = 0;
|
||||
memset(switchap_bssid, 0, sizeof(switchap_bssid));
|
||||
elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_BSSID, &len, NULL);
|
||||
|
||||
if (elem != NULL && len == AWSS_BSSID_STR_LEN) {
|
||||
uint8_t i = 0;
|
||||
char *bssid_str = elem;
|
||||
/* convert bssid string to bssid value */
|
||||
while (i < OS_ETH_ALEN) {
|
||||
switchap_bssid[i ++] = (uint8_t)strtol(bssid_str, &bssid_str, 16);
|
||||
++ bssid_str;
|
||||
/*
|
||||
* fix the format of bssid string is not legal.
|
||||
*/
|
||||
if ((uint32_t)((unsigned long)bssid_str - (unsigned long)elem) > AWSS_BSSID_STR_LEN) {
|
||||
memset(switchap_bssid, 0, sizeof(switchap_bssid));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len = 0;
|
||||
elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_SWITCH_MODE, &len, NULL);
|
||||
if (elem != NULL && (elem[0] == '0' || elem[0] == 0)) {
|
||||
elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_TIMEOUT, &len, NULL);
|
||||
if (elem) {
|
||||
timeout = (int)strtol(elem, &elem, 16);
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
/* reduce stack used */
|
||||
char *id = NULL;
|
||||
char id_str[MSG_REQ_ID_LEN] = {0};
|
||||
id = json_get_value_by_name(payload, payload_len, AWSS_JSON_ID, &len, NULL);
|
||||
memcpy(id_str, id, len > MSG_REQ_ID_LEN - 1 ? MSG_REQ_ID_LEN - 1 : len);
|
||||
awss_build_packet(AWSS_CMP_PKT_TYPE_RSP, id_str, ILOP_VER, METHOD_EVENT_ZC_SWITCHAP, "{}", 200, packet, &packet_len);
|
||||
} while (0);
|
||||
|
||||
do {
|
||||
char reply[TOPIC_LEN_MAX] = {0};
|
||||
awss_build_topic(TOPIC_SWITCHAP_REPLY, reply, TOPIC_LEN_MAX);
|
||||
awss_cmp_mqtt_send(reply, packet, packet_len, 1);
|
||||
HAL_Free(packet);
|
||||
} while (0);
|
||||
|
||||
/*
|
||||
* make sure the response would been received
|
||||
*/
|
||||
if (timeout < 1000) {
|
||||
timeout = 1000;
|
||||
}
|
||||
|
||||
do {
|
||||
uint8_t bssid[ETH_ALEN] = {0};
|
||||
char ssid[OS_MAX_SSID_LEN + 1] = {0}, passwd[OS_MAX_PASSWD_LEN + 1] = {0};
|
||||
HAL_Wifi_Get_Ap_Info(ssid, passwd, bssid);
|
||||
/*
|
||||
* switch ap when destination ap is differenct from current ap
|
||||
*/
|
||||
if (strncmp(ssid, switchap_ssid, sizeof(ssid)) ||
|
||||
memcmp(bssid, switchap_bssid, sizeof(bssid)) ||
|
||||
strncmp(passwd, switchap_passwd, sizeof(passwd))) {
|
||||
if (switchap_timer == NULL) {
|
||||
switchap_timer = HAL_Timer_Create("swichap_online", (void (*)(void *))awss_switch_ap_online, NULL);
|
||||
}
|
||||
|
||||
HAL_Timer_Stop(switchap_timer);
|
||||
HAL_Timer_Start(switchap_timer, timeout);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return;
|
||||
|
||||
ONLINE_SWITCHAP_FAIL:
|
||||
awss_warn("ilop online switchap failed");
|
||||
memset(switchap_ssid, 0, sizeof(switchap_ssid));
|
||||
memset(switchap_bssid, 0, sizeof(switchap_bssid));
|
||||
memset(switchap_passwd, 0, sizeof(switchap_passwd));
|
||||
if (packet) {
|
||||
HAL_Free(packet);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void *reboot_timer = NULL;
|
||||
static int awss_switch_ap_online()
|
||||
{
|
||||
HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT_MS, switchap_ssid, switchap_passwd,
|
||||
AWSS_AUTH_TYPE_INVALID, AWSS_ENC_TYPE_INVALID, switchap_bssid, 0);
|
||||
|
||||
awss_stop_timer(switchap_timer);
|
||||
switchap_timer = NULL;
|
||||
|
||||
memset(switchap_ssid, 0, sizeof(switchap_ssid));
|
||||
memset(switchap_bssid, 0, sizeof(switchap_bssid));
|
||||
memset(switchap_passwd, 0, sizeof(switchap_passwd));
|
||||
|
||||
reboot_timer = HAL_Timer_Create("rb_timer", (void (*)(void *))awss_reboot_system, NULL);
|
||||
HAL_Timer_Start(reboot_timer, 1000);;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int awss_reboot_system()
|
||||
{
|
||||
awss_stop_timer(reboot_timer);
|
||||
reboot_timer = NULL;
|
||||
HAL_Reboot();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int awss_report_token_to_cloud()
|
||||
{
|
||||
int packet_len, ret;
|
||||
char *packet;
|
||||
char topic[TOPIC_LEN_MAX] = {0};
|
||||
#define REPORT_TOKEN_PARAM_LEN (64)
|
||||
if (awss_report_token_suc) { /* success ,no need to report */
|
||||
return 0;
|
||||
}
|
||||
|
||||
AWSS_DB_UPDATE_STATIS(AWSS_DB_STATIS_START);
|
||||
|
||||
/*
|
||||
* it is still failed after try to report token MATCH_REPORT_CNT_MAX times
|
||||
*/
|
||||
if (awss_report_token_cnt ++ > MATCH_REPORT_CNT_MAX) {
|
||||
awss_stop_timer(report_token_timer);
|
||||
report_token_timer = NULL;
|
||||
awss_info("try %d times fail", awss_report_token_cnt);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (report_token_timer == NULL) {
|
||||
report_token_timer = HAL_Timer_Create("rp_token", (void (*)(void *))awss_report_token_to_cloud, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(report_token_timer);
|
||||
HAL_Timer_Start(report_token_timer, 3 * 1000);
|
||||
|
||||
packet_len = AWSS_REPORT_LEN_MAX;
|
||||
|
||||
packet = os_zalloc(packet_len + 1);
|
||||
if (packet == NULL) {
|
||||
awss_err("alloc mem(%d) failed", packet_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
/* reduce stack used */
|
||||
uint8_t i;
|
||||
char id_str[MSG_REQ_ID_LEN] = {0};
|
||||
char param[REPORT_TOKEN_PARAM_LEN] = {0};
|
||||
char token_str[(RANDOM_MAX_LEN << 1) + 1] = {0};
|
||||
|
||||
for (i = 0; i < sizeof(aes_random); i ++) /* check aes_random is initialed or not */
|
||||
if (aes_random[i] != 0x00) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= sizeof(aes_random)) { /* aes_random needs to be initialed */
|
||||
produce_random(aes_random, sizeof(aes_random));
|
||||
}
|
||||
|
||||
awss_report_token_time = os_get_time_ms();
|
||||
|
||||
HAL_Snprintf(id_str, MSG_REQ_ID_LEN - 1, "\"%u\"", awss_report_id ++);
|
||||
utils_hex_to_str(aes_random, RANDOM_MAX_LEN, token_str, sizeof(token_str) - 1);
|
||||
HAL_Snprintf(param, REPORT_TOKEN_PARAM_LEN - 1, "{\"token\":\"%s\"}", token_str);
|
||||
awss_build_packet(AWSS_CMP_PKT_TYPE_REQ, id_str, ILOP_VER, METHOD_MATCH_REPORT, param, 0, packet, &packet_len);
|
||||
} while (0);
|
||||
|
||||
awss_debug("report token:%s\r\n", packet);
|
||||
awss_build_topic(TOPIC_MATCH_REPORT, topic, TOPIC_LEN_MAX);
|
||||
|
||||
ret = awss_cmp_mqtt_send(topic, packet, packet_len, 1);
|
||||
awss_info("report token res:%d\r\n", ret);
|
||||
HAL_Free(packet);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int awss_report_token()
|
||||
{
|
||||
awss_report_token_cnt = 0;
|
||||
awss_report_token_suc = 0;
|
||||
|
||||
return awss_report_token_to_cloud();
|
||||
}
|
||||
|
||||
int awss_stop_report_token()
|
||||
{
|
||||
if (report_token_timer) {
|
||||
awss_stop_timer(report_token_timer);
|
||||
report_token_timer = NULL;
|
||||
}
|
||||
|
||||
memset(aes_random, 0x00, sizeof(aes_random));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef __AWSS_RESET__
|
||||
#define __AWSS_RESET__
|
||||
|
||||
#define AWSS_RESET_PKT_LEN (256)
|
||||
#define AWSS_RESET_TOPIC_LEN (128)
|
||||
#define AWSS_RESET_MSG_ID_LEN (16)
|
||||
|
||||
#define TOPIC_RESET_REPORT "/sys/%s/%s/thing/reset"
|
||||
#define TOPIC_RESET_REPORT_REPLY "/sys/%s/%s/thing/reset_reply"
|
||||
#define METHOD_RESET_REPORT "thing.reset"
|
||||
|
||||
#define AWSS_RESET_REQ_FMT "{\"id\":%s, \"version\":\"1.0\", \"method\":\"%s\", \"params\":%s}"
|
||||
|
||||
#define AWSS_KV_RST "awss.rst"
|
||||
|
||||
int awss_check_reset();
|
||||
|
||||
/**
|
||||
* @brief report reset to cloud.
|
||||
*
|
||||
* @retval -1 : failure
|
||||
* @retval 0 : sucess
|
||||
* @note
|
||||
* device will save reset flag if device dosen't connect cloud, device will fails to send reset to cloud.
|
||||
* when connection between device and cloud is ready, device will retry to report reset to cloud.
|
||||
*/
|
||||
int awss_report_reset();
|
||||
|
||||
/**
|
||||
* @brief stop to report reset to cloud.
|
||||
*
|
||||
* @retval -1 : failure
|
||||
* @retval 0 : sucess
|
||||
* @note
|
||||
* just stop report reset to cloud without any touch reset flag in flash.
|
||||
*/
|
||||
int awss_stop_report_reset();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AWSS_RESET_PKT_LEN (256)
|
||||
#define AWSS_RESET_TOPIC_LEN (128)
|
||||
#define AWSS_RESET_MSG_ID_LEN (16)
|
||||
|
||||
#define TOPIC_RESET_REPORT "/sys/%s/%s/thing/reset"
|
||||
#define TOPIC_RESET_REPORT_REPLY "/sys/%s/%s/thing/reset_reply"
|
||||
#define METHOD_RESET_REPORT "thing.reset"
|
||||
|
||||
#define AWSS_RESET_REQ_FMT "{\"id\":%s, \"version\":\"1.0\", \"method\":\"%s\", \"params\":%s}"
|
||||
|
||||
#define AWSS_KV_RST "awss.rst"
|
||||
#define AWSS_KV_RST_FLAG "awss.rst.flag"
|
||||
|
||||
static uint8_t awss_report_reset_suc = 0;
|
||||
static uint16_t awss_report_reset_id = 0;
|
||||
static void *report_reset_timer = NULL;
|
||||
|
||||
static int awss_report_reset_to_cloud();
|
||||
|
||||
void awss_report_reset_reply(void *pcontext, void *pclient, void *mesg)
|
||||
{
|
||||
char rst = 0;
|
||||
|
||||
iotx_mqtt_event_msg_pt msg = (iotx_mqtt_event_msg_pt)mesg;
|
||||
|
||||
switch (msg->event_type) {
|
||||
case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
devrst_debug("[RST]", "%s\r\n", __func__);
|
||||
|
||||
awss_report_reset_suc = 1;
|
||||
HAL_Kv_Set(AWSS_KV_RST, &rst, sizeof(rst), 0);
|
||||
|
||||
HAL_Timer_Stop(report_reset_timer);
|
||||
HAL_Timer_Delete(report_reset_timer);
|
||||
report_reset_timer = NULL;
|
||||
|
||||
#ifdef INFRA_EVENT
|
||||
iotx_event_post(IOTX_RESET); /* for old version of event */
|
||||
do { /* for new version of event */
|
||||
void *cb = NULL;
|
||||
cb = (void *)iotx_event_callback(ITE_AWSS_STATUS);
|
||||
if (cb == NULL) {
|
||||
break;
|
||||
}
|
||||
((int (*)(int))cb)(IOTX_RESET);
|
||||
} while (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int awss_report_reset_to_cloud()
|
||||
{
|
||||
int ret = -1;
|
||||
int final_len = 0;
|
||||
char *topic = NULL;
|
||||
char *packet = NULL;
|
||||
int packet_len = AWSS_RESET_PKT_LEN;
|
||||
int topic_len = AWSS_RESET_TOPIC_LEN;
|
||||
|
||||
if (awss_report_reset_suc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (report_reset_timer == NULL) {
|
||||
report_reset_timer = HAL_Timer_Create("report_rst", (void (*)(void *))awss_report_reset_to_cloud, NULL);
|
||||
}
|
||||
HAL_Timer_Stop(report_reset_timer);
|
||||
HAL_Timer_Start(report_reset_timer, 3000);
|
||||
do {
|
||||
char pk[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char dn[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
HAL_GetProductKey(pk);
|
||||
HAL_GetDeviceName(dn);
|
||||
|
||||
topic = (char *)devrst_malloc(topic_len + 1);
|
||||
if (topic == NULL) {
|
||||
goto REPORT_RST_ERR;
|
||||
}
|
||||
memset(topic, 0, topic_len + 1);
|
||||
|
||||
HAL_Snprintf(topic, topic_len, TOPIC_RESET_REPORT_REPLY, pk, dn);
|
||||
|
||||
ret = IOT_MQTT_Subscribe_Sync(NULL, topic, IOTX_MQTT_QOS0,
|
||||
(iotx_mqtt_event_handle_func_fpt)awss_report_reset_reply, NULL, 1000);
|
||||
if (ret < 0) {
|
||||
goto REPORT_RST_ERR;
|
||||
}
|
||||
|
||||
memset(topic, 0, topic_len + 1);
|
||||
HAL_Snprintf(topic, topic_len, TOPIC_RESET_REPORT, pk, dn);
|
||||
} while (0);
|
||||
|
||||
packet = devrst_malloc(packet_len + 1);
|
||||
if (packet == NULL) {
|
||||
ret = -1;
|
||||
goto REPORT_RST_ERR;
|
||||
}
|
||||
memset(packet, 0, packet_len + 1);
|
||||
|
||||
do {
|
||||
char id_str[AWSS_RESET_MSG_ID_LEN + 1] = {0};
|
||||
HAL_Snprintf(id_str, AWSS_RESET_MSG_ID_LEN, "\"%u\"", awss_report_reset_id ++);
|
||||
final_len = HAL_Snprintf(packet, packet_len, AWSS_RESET_REQ_FMT, id_str, METHOD_RESET_REPORT, "{}");
|
||||
} while (0);
|
||||
|
||||
devrst_debug("[RST]", "report reset:%s\r\n", packet);
|
||||
|
||||
ret = IOT_MQTT_Publish_Simple(NULL, topic, IOTX_MQTT_QOS0, packet, final_len);
|
||||
devrst_debug("[RST]", "report reset result:%d\r\n", ret);
|
||||
|
||||
REPORT_RST_ERR:
|
||||
if (packet) {
|
||||
devrst_free(packet);
|
||||
}
|
||||
if (topic) {
|
||||
devrst_free(topic);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int awss_report_reset()
|
||||
{
|
||||
char rst = 0;
|
||||
int ret = 0, len = 1;
|
||||
awss_report_reset_suc = 0;
|
||||
|
||||
HAL_Kv_Get(AWSS_KV_RST_FLAG, &rst, &len);
|
||||
|
||||
if (!rst) {
|
||||
ret = 1;
|
||||
/* guocheng.kgc add for filter unbind msg when device reset */
|
||||
HAL_Kv_Set(AWSS_KV_RST_FLAG, &rst, sizeof(rst), 0);
|
||||
ret = HAL_Kv_Set(AWSS_KV_RST, &rst, sizeof(rst), 0);
|
||||
if (ret < 0) {
|
||||
devrst_err("[RST]", "set %s result is %d\r\n", AWSS_KV_RST, ret);
|
||||
}
|
||||
return awss_report_reset_to_cloud();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int awss_check_reset()
|
||||
{
|
||||
int len = 1;
|
||||
char rst = 0;
|
||||
|
||||
HAL_Kv_Get(AWSS_KV_RST, &rst, &len);
|
||||
|
||||
if (rst != 0x01) { /* reset flag is not set */
|
||||
devrst_debug("[RST]", "no rst\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
awss_report_reset_suc = 0;
|
||||
|
||||
return awss_report_reset_to_cloud();
|
||||
}
|
||||
|
||||
int awss_stop_report_reset()
|
||||
{
|
||||
if (report_reset_timer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_Timer_Stop(report_reset_timer);
|
||||
HAL_Timer_Delete(report_reset_timer);
|
||||
report_reset_timer = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef _AWSS_DEV_RESET_INTERNAL_H_
|
||||
#define _AWSS_DEV_RESET_INTERNAL_H_
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#ifdef INFRA_LOG
|
||||
#include "infra_log.h"
|
||||
#define devrst_err(...) log_err("devrst", __VA_ARGS__)
|
||||
#define devrst_info(...) log_info("devrst", __VA_ARGS__)
|
||||
#define devrst_debug(...) log_debug("devrst", __VA_ARGS__)
|
||||
#else
|
||||
#define devrst_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define devrst_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define devrst_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#endif
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define devrst_malloc(size) LITE_malloc(size, MEM_MAGIC, "devrst")
|
||||
#define devrst_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define devrst_malloc(size) HAL_Malloc(size)
|
||||
#define devrst_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int awss_stop_timer(void *timer)
|
||||
{
|
||||
if (timer == NULL)
|
||||
return 0;
|
||||
HAL_Timer_Stop(timer);
|
||||
HAL_Timer_Delete(timer);
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
int awss_start_timer(void **timer, const char *name, void *func, void *user_data, int ms)
|
||||
{
|
||||
if (timer == NULL)
|
||||
return -1;
|
||||
*timer = HAL_Timer_Create(name, (void (*)(void *))func, user_data);
|
||||
if (*timer == NULL)
|
||||
return -1;
|
||||
HAL_Timer_Stop(*timer);
|
||||
HAL_Timer_Start(*timer, ms);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_TIMER_H__
|
||||
#define __AWSS_TIMER_H__
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int awss_stop_timer(void *timer);
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_UTILS_H__
|
||||
#define __AWSS_UTILS_H__
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "os.h"
|
||||
#if 0
|
||||
#include "iotx_utils.h"
|
||||
#endif
|
||||
#include "infra_string.h"
|
||||
|
||||
/**
|
||||
* @brief string to hex
|
||||
*
|
||||
* @param[in] str: input hex string
|
||||
* @param[in] str_len: length of input hex string
|
||||
* @param[out] out: output hex byte stream
|
||||
* @param[in/out] output_len: [in] for output buffer size, [out] for
|
||||
* output hex byte len
|
||||
* @Note None.
|
||||
*
|
||||
* @retval return num of hex bytes converted, 0 means error.
|
||||
*/
|
||||
#define utils_str_to_hex LITE_hexstr_convert
|
||||
|
||||
|
||||
/**
|
||||
* @brief hex to string
|
||||
*
|
||||
* @param[in] buf: input hex byte stream
|
||||
* @param[in] buf_len: input stream length in byte
|
||||
* @param[out] str: encoded hex string
|
||||
* @param[in/out] str_len: [in] for str buffer size, [out] for
|
||||
* encoded string length
|
||||
* @Note output str buffer is NULL-terminated(if str_buf_len is longer enough)
|
||||
*
|
||||
* @retval return length of str converted, 0 means error.
|
||||
*/
|
||||
#define utils_hex_to_str(buf, buf_len, str, str_buf_len) LITE_hexbuf_convert(buf, str, buf_len, 1)
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "infra_config.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "awss_event.h"
|
||||
#include "awss_timer.h"
|
||||
#include "awss_log.h"
|
||||
#include "passwd.h"
|
||||
#include "awss_utils.h"
|
||||
#include "awss_reset.h"
|
||||
#include "infra_compat.h"
|
||||
#include "awss_packet.h"
|
||||
#include "awss_notify.h"
|
||||
#include "awss_cmp.h"
|
||||
#include "awss_cmp.h"
|
||||
#include "sha256.h"
|
||||
#include "infra_json_parser.h"
|
||||
#include "mqtt_api.h"
|
||||
#include "awss_dev_reset_internal.h"
|
||||
#include "awss_info.h"
|
||||
#include "awss_bind_statis.h"
|
||||
#include "dev_bind_wrapper.h"
|
||||
#include "coap_api.h"
|
||||
#include "iotx_coap.h"
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
#include "awss_statis.h"
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __IOT_IMPORT_AWSS_H__
|
||||
#define __IOT_IMPORT_AWSS_H__
|
||||
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DLL_HAL_API
|
||||
#define DLL_HAL_API
|
||||
#endif
|
||||
#ifndef _IN_
|
||||
#define _IN_
|
||||
#endif
|
||||
#ifndef _OU_
|
||||
#define _OU_
|
||||
#endif
|
||||
#ifndef _IN_OPT_
|
||||
#define _IN_OPT_
|
||||
#endif
|
||||
|
||||
/* link type */
|
||||
enum AWSS_LINK_TYPE {
|
||||
/* rtos HAL choose this type */
|
||||
AWSS_LINK_TYPE_NONE,
|
||||
|
||||
/* linux HAL may choose the following type */
|
||||
AWSS_LINK_TYPE_PRISM,
|
||||
AWSS_LINK_TYPE_80211_RADIO,
|
||||
AWSS_LINK_TYPE_80211_RADIO_AVS,
|
||||
AWSS_LINK_TYPE_HT40_CTRL /* for espressif HAL, see struct ht40_ctrl */
|
||||
};
|
||||
|
||||
struct HAL_Ht40_Ctrl {
|
||||
uint16_t length;
|
||||
uint8_t filter;
|
||||
signed char rssi;
|
||||
};
|
||||
|
||||
typedef int (*awss_recv_80211_frame_cb_t)(char *buf, int length,
|
||||
enum AWSS_LINK_TYPE link_type, int with_fcs, signed char rssi);
|
||||
|
||||
/* auth type */
|
||||
enum AWSS_AUTH_TYPE {
|
||||
AWSS_AUTH_TYPE_OPEN,
|
||||
AWSS_AUTH_TYPE_SHARED,
|
||||
AWSS_AUTH_TYPE_WPAPSK,
|
||||
AWSS_AUTH_TYPE_WPA8021X,
|
||||
AWSS_AUTH_TYPE_WPA2PSK,
|
||||
AWSS_AUTH_TYPE_WPA28021X,
|
||||
AWSS_AUTH_TYPE_WPAPSKWPA2PSK,
|
||||
AWSS_AUTH_TYPE_MAX = AWSS_AUTH_TYPE_WPAPSKWPA2PSK,
|
||||
AWSS_AUTH_TYPE_INVALID = 0xff,
|
||||
};
|
||||
|
||||
/* encryt type */
|
||||
enum AWSS_ENC_TYPE {
|
||||
AWSS_ENC_TYPE_NONE,
|
||||
AWSS_ENC_TYPE_WEP,
|
||||
AWSS_ENC_TYPE_TKIP,
|
||||
AWSS_ENC_TYPE_AES,
|
||||
AWSS_ENC_TYPE_TKIPAES,
|
||||
AWSS_ENC_TYPE_MAX = AWSS_ENC_TYPE_TKIPAES,
|
||||
AWSS_ENC_TYPE_INVALID = 0xff,
|
||||
};
|
||||
|
||||
typedef int (*awss_wifi_scan_result_cb_t)(
|
||||
const char ssid[HAL_MAX_SSID_LEN],
|
||||
const uint8_t bssid[ETH_ALEN],
|
||||
enum AWSS_AUTH_TYPE auth,
|
||||
enum AWSS_ENC_TYPE encry,
|
||||
uint8_t channel, signed char rssi,
|
||||
int is_last_ap);
|
||||
|
||||
/* 80211 frame type */
|
||||
typedef enum HAL_Awss_Frame_Type {
|
||||
FRAME_ACTION,
|
||||
FRAME_BEACON,
|
||||
FRAME_PROBE_REQ,
|
||||
FRAME_PROBE_RESPONSE,
|
||||
FRAME_DATA
|
||||
} HAL_Awss_Frame_Type_t;
|
||||
|
||||
#define FRAME_ACTION_MASK (1 << FRAME_ACTION)
|
||||
#define FRAME_BEACON_MASK (1 << FRAME_BEACON)
|
||||
#define FRAME_PROBE_REQ_MASK (1 << FRAME_PROBE_REQ)
|
||||
#define FRAME_PROBE_RESP_MASK (1 << FRAME_PROBE_RESPONSE)
|
||||
#define FRAME_DATA_MASK (1 << FRAME_DATA)
|
||||
|
||||
typedef void (*awss_wifi_mgmt_frame_cb_t)(_IN_ uint8_t *buffer, _IN_ int len,
|
||||
_IN_ signed char rssi_dbm, _IN_ int buffer_type);
|
||||
|
||||
typedef struct {
|
||||
enum AWSS_AUTH_TYPE auth;
|
||||
enum AWSS_ENC_TYPE encry;
|
||||
uint8_t channel;
|
||||
signed char rssi_dbm;
|
||||
char ssid[HAL_MAX_SSID_LEN];
|
||||
uint8_t mac[ETH_ALEN];
|
||||
} awss_ap_info_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __IOT_IMPORT_AWSS_H__ */
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_OS_H__
|
||||
#define __AWSS_OS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include "infra_defs.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "infra_compat.h"
|
||||
|
||||
#ifndef _IN_OPT_
|
||||
#define _IN_OPT_
|
||||
#endif
|
||||
#ifndef _OUT_
|
||||
#define _OUT_
|
||||
#endif
|
||||
#ifndef _OUT_OPT_
|
||||
#define _OUT_OPT_
|
||||
#endif
|
||||
#ifndef _INOUT_
|
||||
#define _INOUT_
|
||||
#endif
|
||||
#ifndef _INOUT_OPT_
|
||||
#define _INOUT_OPT_
|
||||
#endif
|
||||
|
||||
/** @defgroup group_os os
|
||||
* @{
|
||||
*/
|
||||
#define OS_MAC_LEN HAL_MAC_LEN
|
||||
#define OS_ETH_ALEN ETH_ALEN
|
||||
#define OS_IP_LEN (NETWORK_ADDR_LEN)
|
||||
#define OS_MAX_PASSWD_LEN HAL_MAX_PASSWD_LEN
|
||||
#define OS_MAX_SSID_LEN HAL_MAX_SSID_LEN
|
||||
#define OS_PRODUCT_KEY_LEN IOTX_PRODUCT_KEY_LEN
|
||||
#define OS_PRODUCT_SECRET_LEN IOTX_PRODUCT_SECRET_LEN
|
||||
#define OS_DEVICE_NAME_LEN IOTX_DEVICE_NAME_LEN
|
||||
#define OS_DEVICE_SECRET_LEN IOTX_DEVICE_SECRET_LEN
|
||||
#define PLATFORM_AES_DECRYPTION HAL_AES_DECRYPTION
|
||||
#define PLATFORM_AES_ENCRYPTION HAL_AES_ENCRYPTION
|
||||
#define PLATFORM_MAX_SSID_LEN HAL_MAX_SSID_LEN
|
||||
#define PLATFORM_MAX_PASSWD_LEN HAL_MAX_PASSWD_LEN
|
||||
typedef void *p_HAL_Aes128_t;
|
||||
#define p_aes128_t p_HAL_Aes128_t
|
||||
|
||||
char *os_wifi_get_mac_str(char mac_str[HAL_MAC_LEN]);
|
||||
char *os_wifi_str2mac(char mac_str[HAL_MAC_LEN], char mac[ETH_ALEN]);
|
||||
uint8_t *os_wifi_get_mac(uint8_t mac[ETH_ALEN]);
|
||||
uint32_t os_get_time_ms(void);
|
||||
|
||||
int os_is_big_endian(void);
|
||||
uint16_t os_htobe16(uint16_t data);
|
||||
uint16_t os_htole16(uint16_t data);
|
||||
uint16_t os_be16toh(uint16_t data);
|
||||
uint16_t os_le16toh(uint16_t data);
|
||||
uint32_t os_le32toh(uint32_t data);
|
||||
uint16_t os_get_unaligned_be16(uint8_t *ptr);
|
||||
uint16_t os_get_unaligned_le16(uint8_t *ptr);
|
||||
uint32_t os_get_unaligned_be32(uint8_t *ptr);
|
||||
uint32_t os_get_unaligned_le32(uint8_t *ptr);
|
||||
void *os_zalloc(uint32_t size);
|
||||
uint32_t time_elapsed_ms_since(uint32_t start_timestamp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SRC_OSA_ABSTRAC_H_ */
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
/****** Convert values between host and big-/little-endian byte order ******/
|
||||
|
||||
/* reverse byte order */
|
||||
static uint16_t reverse_16bit(uint16_t data)
|
||||
{
|
||||
return (data >> 8) | (data << 8);
|
||||
}
|
||||
|
||||
/* host byte order to big endian */
|
||||
uint16_t os_htobe16(uint16_t data)
|
||||
{
|
||||
if (os_is_big_endian()) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return reverse_16bit(data);
|
||||
}
|
||||
|
||||
/* host byte order to little endian */
|
||||
uint16_t os_htole16(uint16_t data)
|
||||
{
|
||||
if (os_is_big_endian()) {
|
||||
return reverse_16bit(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* big endian to host byte order */
|
||||
uint16_t os_be16toh(uint16_t data)
|
||||
{
|
||||
return os_htobe16(data);
|
||||
}
|
||||
|
||||
/* little endian to host byte order */
|
||||
uint16_t os_le16toh(uint16_t data)
|
||||
{
|
||||
return os_htole16(data);
|
||||
}
|
||||
|
||||
/* get unaligned data in big endian. */
|
||||
uint16_t os_get_unaligned_be16(uint8_t * ptr)
|
||||
{
|
||||
uint16_t res;
|
||||
|
||||
memcpy(&res, ptr, sizeof(uint16_t));
|
||||
|
||||
return os_be16toh(res);
|
||||
}
|
||||
|
||||
/* get unaligned data in little endian. */
|
||||
uint16_t os_get_unaligned_le16(uint8_t * ptr)
|
||||
{
|
||||
uint16_t res;
|
||||
|
||||
memcpy(&res, ptr, sizeof(uint16_t));
|
||||
|
||||
return os_le16toh(res);
|
||||
|
||||
}
|
||||
|
||||
/* format mac string uppercase */
|
||||
char *os_wifi_get_mac_str(char mac_str[OS_MAC_LEN])
|
||||
{
|
||||
char *str;
|
||||
int colon_num = 0, i;
|
||||
|
||||
str = HAL_Wifi_Get_Mac(mac_str);
|
||||
|
||||
/* sanity check */
|
||||
while (str) {
|
||||
str = strchr(str, ':');
|
||||
if (str) {
|
||||
colon_num ++;
|
||||
str ++; /* eating char ':' */
|
||||
}
|
||||
}
|
||||
|
||||
/* convert to capital letter */
|
||||
for (i = 0; i < OS_MAC_LEN && mac_str[i]; i ++) {
|
||||
if ('a' <= mac_str[i] && mac_str[i] <= 'z') {
|
||||
mac_str[i] -= 'a' - 'A';
|
||||
}
|
||||
}
|
||||
|
||||
return mac_str;
|
||||
}
|
||||
char *os_wifi_str2mac(char mac_str[OS_MAC_LEN], char mac[OS_ETH_ALEN])
|
||||
{
|
||||
int i = 0;
|
||||
char *ptr = mac_str;
|
||||
char mac_addr[OS_ETH_ALEN] = {0};
|
||||
|
||||
if (ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
while (isxdigit((int)*ptr) && i < OS_ETH_ALEN) {
|
||||
mac_addr[i ++] = (uint8_t)strtol(ptr, &ptr, 16);
|
||||
++ ptr;
|
||||
}
|
||||
|
||||
if (i < OS_ETH_ALEN) /* don't touch mac when fail */
|
||||
return NULL;
|
||||
|
||||
if (mac) memcpy(mac, mac_addr, OS_ETH_ALEN);
|
||||
|
||||
return mac;
|
||||
}
|
||||
|
||||
uint8_t *os_wifi_get_mac(uint8_t mac[OS_ETH_ALEN])
|
||||
{
|
||||
char mac_str[OS_MAC_LEN] = {0};
|
||||
|
||||
os_wifi_get_mac_str(mac_str);
|
||||
|
||||
return (uint8_t *)os_wifi_str2mac(mac_str, (char *)mac);
|
||||
}
|
||||
|
||||
void *os_zalloc(uint32_t size)
|
||||
{
|
||||
void *ptr = HAL_Malloc(size);
|
||||
if (ptr != NULL) {
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint32_t os_get_time_ms(void)
|
||||
{
|
||||
static uint32_t fixed_delta;
|
||||
|
||||
if (!fixed_delta) {
|
||||
fixed_delta = (uint32_t)HAL_UptimeMs() - 0xFFFF0000;
|
||||
}
|
||||
|
||||
/* add a big offset, for easier caught time overflow bug */
|
||||
return (uint32_t)HAL_UptimeMs() - fixed_delta;
|
||||
}
|
||||
|
||||
uint32_t time_elapsed_ms_since(uint32_t start_timestamp)
|
||||
{
|
||||
uint32_t now = os_get_time_ms();
|
||||
return now - start_timestamp;
|
||||
}
|
||||
|
||||
int os_is_big_endian(void)
|
||||
{
|
||||
uint32_t data = 0xFF000000;
|
||||
|
||||
if (0xFF == *(uint8_t *) & data) {
|
||||
return 1; /* big endian */
|
||||
}
|
||||
|
||||
return 0; /* little endian */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
uint8_t aes_random[RANDOM_MAX_LEN] = {0};
|
||||
|
||||
int awss_set_token(uint8_t token[RANDOM_MAX_LEN])
|
||||
{
|
||||
char rand_str[(RANDOM_MAX_LEN << 1) + 1] = {0};
|
||||
if (token == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(aes_random, token, RANDOM_MAX_LEN);
|
||||
utils_hex_to_str(aes_random, RANDOM_MAX_LEN, rand_str, sizeof(rand_str));
|
||||
awss_trace("bind: app token set %s", rand_str);
|
||||
return 0;
|
||||
}
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
/*
|
||||
* 1. place 0 @ 0, because of java modified-UTF8
|
||||
* 2. translation follow utf8 stardard
|
||||
*/
|
||||
static const uint8_t ssid_dict_decode_table[] = {
|
||||
0x00, 0x0e, 0x6c, 0x3a, 0x6d, 0x44, 0x2a, 0x6f,
|
||||
0x4d, 0x05, 0x6b, 0x28, 0x08, 0x25, 0x5f, 0x2d,
|
||||
0x64, 0x76, 0x78, 0x37, 0x58, 0x60, 0x53, 0x31,
|
||||
0x36, 0x79, 0x43, 0x1a, 0x11, 0x72, 0x03, 0x59,
|
||||
0x50, 0x02, 0x71, 0x7c, 0x34, 0x3e, 0x23, 0x24,
|
||||
0x26, 0x5b, 0x73, 0x0f, 0x5e, 0x12, 0x54, 0x0b,
|
||||
0x61, 0x35, 0x3c, 0x57, 0x48, 0x55, 0x63, 0x4a,
|
||||
0x13, 0x75, 0x45, 0x70, 0x47, 0x0c, 0x2f, 0x21,
|
||||
0x17, 0x2e, 0x62, 0x49, 0x4b, 0x5c, 0x19, 0x51,
|
||||
0x69, 0x3b, 0x7e, 0x0d, 0x3d, 0x67, 0x2c, 0x22,
|
||||
0x14, 0x42, 0x5a, 0x7f, 0x32, 0x01, 0x07, 0x7b,
|
||||
0x15, 0x4f, 0x16, 0x29, 0x30, 0x27, 0x20, 0x18,
|
||||
0x65, 0x06, 0x1c, 0x3f, 0x68, 0x2b, 0x4c, 0x0a,
|
||||
0x1e, 0x46, 0x5d, 0x1f, 0x10, 0x6e, 0x56, 0x7a,
|
||||
0x1b, 0x09, 0x52, 0x38, 0x66, 0x7d, 0x41, 0x40,
|
||||
0x04, 0x6a, 0x39, 0x77, 0x33, 0x1d, 0x74, 0x4e,
|
||||
0xaf, 0xa6, 0x8c, 0xbd, 0x89, 0xa2, 0xa9, 0x9e,
|
||||
0xa1, 0x91, 0xb9, 0xad, 0xbf, 0xb7, 0x95, 0xa8,
|
||||
0xa5, 0x82, 0xaa, 0xa3, 0x94, 0x92, 0xb8, 0x87,
|
||||
0x88, 0xb1, 0x93, 0xbc, 0x80, 0xb5, 0xba, 0x99,
|
||||
0xab, 0xbe, 0x90, 0x8e, 0x83, 0x9f, 0x9a, 0x86,
|
||||
0x85, 0x98, 0xa4, 0xa0, 0xac, 0x9c, 0x96, 0x81,
|
||||
0xb0, 0x8d, 0xbb, 0xb2, 0x9d, 0xae, 0x84, 0x9b,
|
||||
0xb4, 0x8b, 0x97, 0xa7, 0xb3, 0x8a, 0x8f, 0xb6,
|
||||
0xc5, 0xc0, 0xc8, 0xd7, 0xde, 0xc4, 0xd1, 0xd2,
|
||||
0xd9, 0xcb, 0xcd, 0xd5, 0xcc, 0xc7, 0xdb, 0xdf,
|
||||
0xdc, 0xdd, 0xcf, 0xc6, 0xda, 0xc2, 0xc3, 0xc9,
|
||||
0xc1, 0xca, 0xd6, 0xd8, 0xce, 0xd3, 0xd0, 0xd4,
|
||||
0xe9, 0xe5, 0xe8, 0xe2, 0xe6, 0xeb, 0xe3, 0xec,
|
||||
0xed, 0xe7, 0xe1, 0xe4, 0xea, 0xef, 0xee, 0xe0,
|
||||
0xf6, 0xf0, 0xf4, 0xf5, 0xf2, 0xf3, 0xf7, 0xf1,
|
||||
0xfb, 0xf9, 0xfa, 0xf8, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
static const uint8_t notify_encode_table[] = {
|
||||
0x00, 0x71, 0x21, 0x1e, 0x78, 0x09, 0x61, 0x56,
|
||||
0x0c, 0x55, 0x67, 0x2f, 0x3d, 0x4b, 0x01, 0x2b,
|
||||
0x6c, 0x1c, 0x1b, 0x38, 0x50, 0x58, 0x5a, 0x40,
|
||||
0x5f, 0x46, 0x2d, 0x70, 0x62, 0x7d, 0x68, 0x6b,
|
||||
0x5e, 0x3f, 0x4f, 0x65, 0x27, 0x0d, 0x28, 0x5d,
|
||||
0x0b, 0x5b, 0x06, 0x26, 0x4e, 0x0f, 0x41, 0x3e,
|
||||
0x5c, 0x17, 0x54, 0x7c, 0x32, 0x31, 0x18, 0x13,
|
||||
0x73, 0x7a, 0x03, 0x49, 0x24, 0x4c, 0x25, 0x63,
|
||||
0x77, 0x76, 0x51, 0x1a, 0x05, 0x08, 0x69, 0x3c,
|
||||
0x34, 0x43, 0x37, 0x44, 0x66, 0x3a, 0x7f, 0x59,
|
||||
0x20, 0x47, 0x72, 0x16, 0x2e, 0x35, 0x2c, 0x33,
|
||||
0x14, 0x1f, 0x52, 0x29, 0x45, 0x6a, 0x6e, 0x0e,
|
||||
0x15, 0x30, 0x42, 0x36, 0x10, 0x60, 0x74, 0x07,
|
||||
0x64, 0x48, 0x79, 0x0a, 0x02, 0x04, 0x6d, 0x4d,
|
||||
0x3b, 0x22, 0x1d, 0x2a, 0x7e, 0x39, 0x1a, 0x7b,
|
||||
0x12, 0x19, 0x6f, 0x57, 0x23, 0x75, 0x41, 0x53,
|
||||
0x9c, 0xaf, 0x91, 0xa4, 0xb6, 0xb1, 0xa7, 0x97,
|
||||
0x98, 0x84, 0xbd, 0xb9, 0x82, 0xa8, 0xa3, 0xbe,
|
||||
0xa2, 0x89, 0x95, 0x9a, 0x94, 0x8e, 0xae, 0xba,
|
||||
0xa9, 0x9f, 0xa6, 0xb7, 0xad, 0xb4, 0x87, 0xa5,
|
||||
0xab, 0x88, 0x85, 0x93, 0xaa, 0x90, 0x81, 0xbb,
|
||||
0x8f, 0x86, 0x92, 0xa0, 0xac, 0x8b, 0xb5, 0x80,
|
||||
0xb0, 0x99, 0xb3, 0xbc, 0xb8, 0x9d, 0xbf, 0x8d,
|
||||
0x96, 0x8a, 0x9e, 0xb2, 0x9b, 0x83, 0xa1, 0x8c,
|
||||
0xc1, 0xd8, 0xd5, 0xd6, 0xc5, 0xc0, 0xd3, 0xcd,
|
||||
0xc2, 0xd7, 0xd9, 0xc9, 0xcc, 0xca, 0xdc, 0xd2,
|
||||
0xde, 0xc6, 0xc7, 0xdd, 0xdf, 0xcb, 0xda, 0xc3,
|
||||
0xdb, 0xc8, 0xd4, 0xce, 0xd0, 0xd1, 0xc4, 0xcf,
|
||||
0xef, 0xea, 0xe3, 0xe6, 0xeb, 0xe1, 0xe4, 0xe9,
|
||||
0xe2, 0xe0, 0xec, 0xe5, 0xe7, 0xe8, 0xee, 0xed,
|
||||
0xf1, 0xf7, 0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf6,
|
||||
0xfb, 0xf9, 0xfa, 0xf8, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
int awss_dict_crypt(char tab_idx, uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
uint8_t *table = NULL;
|
||||
|
||||
switch (tab_idx) {
|
||||
case SSID_DECODE_TABLE:
|
||||
table = (uint8_t *)ssid_dict_decode_table;
|
||||
break;
|
||||
case NOTIFY_ENCODE_TABLE:
|
||||
table = (uint8_t *)notify_encode_table;
|
||||
break;
|
||||
default:
|
||||
table = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (table == NULL || data == NULL)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < len; i ++)
|
||||
data[i] = table[data[i]];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int produce_signature(uint8_t *sign, uint8_t *txt,
|
||||
uint32_t txt_len, const char *key)
|
||||
{
|
||||
if (sign == NULL || txt == NULL || txt_len == 0 || key == NULL)
|
||||
return -1;
|
||||
/* TODO */
|
||||
utils_hmac_sha1_hex((const char *)txt, (int)txt_len,
|
||||
(char *)sign, key, strlen(key));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_PASSWD_H__
|
||||
#define __AWSS_PASSWD_H__
|
||||
|
||||
#define KEY_MAX_LEN (40)
|
||||
#define AES128_KEY_LEN (16)
|
||||
#define RANDOM_MAX_LEN (16)
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SSID_DECODE_TABLE = 0x0,
|
||||
NOTIFY_ENCODE_TABLE,
|
||||
DICT_CRYPT_TABLE_IDX_MAX,
|
||||
};
|
||||
|
||||
int awss_dict_crypt(char tab_idx, uint8_t *data, uint8_t len);
|
||||
#ifdef WIFI_PROVISION_ENABLED
|
||||
int produce_signature(uint8_t *sign, uint8_t *txt, uint32_t txt_len, const char *key);
|
||||
#endif
|
||||
|
||||
extern uint8_t aes_random[RANDOM_MAX_LEN];
|
||||
|
||||
int awss_set_token(uint8_t token[RANDOM_MAX_LEN]);
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
/* Optimized for minimal code size. */
|
||||
#include "dev_bind_internal.h"
|
||||
|
||||
#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
|
||||
#define shr(value, bits) ((value) >> (bits))
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
static const uint32_t K[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
|
||||
|
||||
static void SHA256_Transform(SHA256_CTX* ctx)
|
||||
{
|
||||
uint32_t W[64];
|
||||
uint32_t A, B, C, D, E, F, G, H;
|
||||
uint8_t* p = ctx->buf;
|
||||
int t;
|
||||
|
||||
for(t = 0; t < 16; ++t) {
|
||||
uint32_t tmp = *p++ << 24;
|
||||
tmp |= *p++ << 16;
|
||||
tmp |= *p++ << 8;
|
||||
tmp |= *p++;
|
||||
W[t] = tmp;
|
||||
}
|
||||
|
||||
for(; t < 64; t++) {
|
||||
uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3);
|
||||
uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10);
|
||||
W[t] = W[t-16] + s0 + W[t-7] + s1;
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
E = ctx->state[4];
|
||||
F = ctx->state[5];
|
||||
G = ctx->state[6];
|
||||
H = ctx->state[7];
|
||||
|
||||
for(t = 0; t < 64; t++) {
|
||||
uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
|
||||
uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
|
||||
uint32_t t2 = s0 + maj;
|
||||
uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
|
||||
uint32_t ch = (E & F) ^ ((~E) & G);
|
||||
uint32_t t1 = H + s1 + ch + K[t] + W[t];
|
||||
H = G;
|
||||
G = F;
|
||||
F = E;
|
||||
E = D + t1;
|
||||
D = C;
|
||||
C = B;
|
||||
B = A;
|
||||
A = t1 + t2;
|
||||
}
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
ctx->state[4] += E;
|
||||
ctx->state[5] += F;
|
||||
ctx->state[6] += G;
|
||||
ctx->state[7] += H;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const HASH_VTAB SHA256_VTAB = {
|
||||
SHA256_init,
|
||||
SHA256_update,
|
||||
SHA256_final,
|
||||
SHA256_hash,
|
||||
SHA256_DIGEST_SIZE
|
||||
};
|
||||
#endif
|
||||
|
||||
void SHA256_init(SHA256_CTX* ctx)
|
||||
{
|
||||
/* ctx->f = &SHA256_VTAB;*/
|
||||
ctx->state[0] = 0x6a09e667;
|
||||
ctx->state[1] = 0xbb67ae85;
|
||||
ctx->state[2] = 0x3c6ef372;
|
||||
ctx->state[3] = 0xa54ff53a;
|
||||
ctx->state[4] = 0x510e527f;
|
||||
ctx->state[5] = 0x9b05688c;
|
||||
ctx->state[6] = 0x1f83d9ab;
|
||||
ctx->state[7] = 0x5be0cd19;
|
||||
ctx->count = 0;
|
||||
}
|
||||
|
||||
void SHA256_update(SHA256_CTX* ctx, const void* data, int len)
|
||||
{
|
||||
int i = (int) (ctx->count & 63);
|
||||
const uint8_t* p = (const uint8_t*)data;
|
||||
ctx->count += len;
|
||||
while (len--) {
|
||||
ctx->buf[i++] = *p++;
|
||||
if (i == 64) {
|
||||
SHA256_Transform(ctx);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* SHA256_final(SHA256_CTX* ctx)
|
||||
{
|
||||
uint8_t *p = ctx->buf;
|
||||
uint64_t cnt = ctx->count * 8;
|
||||
int i;
|
||||
SHA256_update(ctx, (uint8_t*)"\x80", 1);
|
||||
while ((ctx->count & 63) != 56) {
|
||||
SHA256_update(ctx, (uint8_t*)"\0", 1);
|
||||
}
|
||||
for (i = 0; i < 8; ++i) {
|
||||
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
|
||||
SHA256_update(ctx, &tmp, 1);
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint32_t tmp = ctx->state[i];
|
||||
*p++ = tmp >> 24;
|
||||
*p++ = tmp >> 16;
|
||||
*p++ = tmp >> 8;
|
||||
*p++ = tmp >> 0;
|
||||
}
|
||||
return ctx->buf;
|
||||
}
|
||||
|
||||
/* Convenience function */
|
||||
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
SHA256_init(&ctx);
|
||||
SHA256_update(&ctx, data, len);
|
||||
memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
|
||||
return digest;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __AWSS_SHA256_H__
|
||||
#define __AWSS_SHA256_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SHA256_CTX {
|
||||
/* const HASH_VTAB * f; */
|
||||
uint64_t count;
|
||||
uint8_t buf[64];
|
||||
uint32_t state[8]; /* upto SHA2 */
|
||||
} SHA256_CTX;
|
||||
|
||||
/* typedef HASH_CTX SHA256_CTX; */
|
||||
void SHA256_init(SHA256_CTX* ctx);
|
||||
void SHA256_update(SHA256_CTX* ctx, const void* data, int len);
|
||||
const uint8_t* SHA256_final(SHA256_CTX* ctx);
|
||||
/* Convenience method. Returns digest address. */
|
||||
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest);
|
||||
|
||||
#ifndef SHA256_DIGEST_SIZE
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus */
|
||||
|
||||
#endif /* SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_ */
|
||||
@@ -0,0 +1,910 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_coap.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "CoAPInternal.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPServer.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "alcs_localsetup.h"
|
||||
#include "CoAPPlatform.h"
|
||||
|
||||
static iotx_alcs_adapter_t g_alcs_adapter;
|
||||
|
||||
static void alcs_heartbeat(void *handle);
|
||||
|
||||
static iotx_alcs_adapter_t *__iotx_alcs_get_ctx(void)
|
||||
{
|
||||
return &g_alcs_adapter;
|
||||
}
|
||||
|
||||
static char *iotx_alcs_topic_parse_pk(char *topic, uint16_t *length)
|
||||
{
|
||||
char *pos = NULL;
|
||||
uint8_t slash_count = 0;
|
||||
uint16_t idx = 0;
|
||||
uint16_t topic_len = 0;
|
||||
|
||||
if (topic == NULL || length == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
topic_len = strlen(topic);
|
||||
|
||||
while (idx < topic_len) {
|
||||
if (topic[idx] == '/') {
|
||||
slash_count++;
|
||||
if (slash_count == 2) {
|
||||
pos = topic + idx + 1;
|
||||
}
|
||||
if (slash_count == 3) {
|
||||
*length = topic + idx - pos;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static char *iotx_alcs_topic_parse_dn(char *topic, uint16_t *length)
|
||||
{
|
||||
char *pos = NULL;
|
||||
uint8_t slash_count = 0;
|
||||
uint16_t idx = 0;
|
||||
uint16_t topic_len = 0;
|
||||
|
||||
if (topic == NULL || length == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
topic_len = strlen(topic);
|
||||
|
||||
while (idx < topic_len) {
|
||||
if (topic[idx] == '/') {
|
||||
slash_count++;
|
||||
if (slash_count == 3) {
|
||||
pos = topic + idx + 1;
|
||||
}
|
||||
if (slash_count == 4) {
|
||||
*length = topic + idx - pos;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static int _iotx_alcs_send_list_search_and_remove(iotx_alcs_adapter_t *adapter, CoAPMessage *message,
|
||||
iotx_alcs_send_msg_t **send_msg)
|
||||
{
|
||||
iotx_alcs_send_msg_t *node = NULL;
|
||||
iotx_alcs_send_msg_t *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &adapter->alcs_send_list, linked_list, iotx_alcs_send_msg_t) {
|
||||
if (message->header.tokenlen == node->token_len &&
|
||||
memcmp(message->token, node->token, node->token_len) == 0) {
|
||||
*send_msg = node;
|
||||
list_del(&node->linked_list);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
void iotx_alcs_coap_adapter_send_msg_handle(CoAPContext *context,
|
||||
CoAPReqResult result,
|
||||
void *userdata,
|
||||
NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)userdata;
|
||||
iotx_alcs_event_msg_t event;
|
||||
memset(&event, 0, sizeof(iotx_alcs_event_msg_t));
|
||||
|
||||
switch (result) {
|
||||
case COAP_REQUEST_SUCCESS: {
|
||||
iotx_alcs_transfer_msg_t transfer_msg;
|
||||
iotx_alcs_send_msg_t *send_msg = NULL;
|
||||
|
||||
memset(&transfer_msg, 0, sizeof(iotx_alcs_transfer_msg_t));
|
||||
|
||||
transfer_msg.ip = (char *)remote->addr;
|
||||
transfer_msg.port = remote->port;
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_send_list_search_and_remove(adapter, message, &send_msg);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
transfer_msg.uri = send_msg->uri;
|
||||
transfer_msg.token_len = send_msg->token_len;
|
||||
transfer_msg.token = send_msg->token;
|
||||
transfer_msg.payload_len = message->payloadlen;
|
||||
transfer_msg.payload = message->payload;
|
||||
|
||||
event.event_type = IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_SUCCESS;
|
||||
event.msg = &transfer_msg;
|
||||
|
||||
adapter->alcs_event_handle->h_fp(adapter->alcs_event_handle->pcontext, (void *)adapter, &event);
|
||||
|
||||
ALCS_free(send_msg->token);
|
||||
ALCS_free(send_msg->uri);
|
||||
ALCS_free(send_msg);
|
||||
}
|
||||
break;
|
||||
case COAP_RECV_RESP_TIMEOUT: {
|
||||
iotx_alcs_transfer_msg_t transfer_msg;
|
||||
iotx_alcs_send_msg_t *send_msg = NULL;
|
||||
|
||||
memset(&transfer_msg, 0, sizeof(iotx_alcs_transfer_msg_t));
|
||||
|
||||
transfer_msg.ip = (char *)remote->addr;
|
||||
transfer_msg.port = remote->port;
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_send_list_search_and_remove(adapter, message, &send_msg);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
transfer_msg.uri = send_msg->uri;
|
||||
transfer_msg.token_len = send_msg->token_len;
|
||||
transfer_msg.token = send_msg->token;
|
||||
transfer_msg.payload_len = 0;
|
||||
transfer_msg.payload = NULL;
|
||||
|
||||
event.event_type = IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_RESP_TIMEOUT;
|
||||
event.msg = &transfer_msg;
|
||||
|
||||
adapter->alcs_event_handle->h_fp(adapter->alcs_event_handle->pcontext, (void *)adapter, &event);
|
||||
|
||||
ALCS_free(send_msg->token);
|
||||
ALCS_free(send_msg->uri);
|
||||
ALCS_free(send_msg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
COAP_WRN("Unknown Coap Request Result: %d", result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void iotx_alcs_coap_adapter_event_notifier(unsigned int event, NetworkAddr *remote, void *message)
|
||||
{
|
||||
COAP_INFO("ALCS Coap Event: %d, Remote Device Address: %s, Remote Device Port: %d",
|
||||
event, remote->addr, remote->port);
|
||||
}
|
||||
|
||||
int iotx_alcs_adapter_list_init(iotx_alcs_adapter_t *adapter)
|
||||
{
|
||||
/* initialze send list */
|
||||
INIT_LIST_HEAD(&adapter->alcs_send_list);
|
||||
INIT_LIST_HEAD(&adapter->alcs_subdev_list);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static void _iotx_alcs_adapter_send_list_destroy(iotx_alcs_adapter_t *adapter)
|
||||
{
|
||||
iotx_alcs_send_msg_t *node = NULL;
|
||||
iotx_alcs_send_msg_t *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &adapter->alcs_send_list, linked_list, iotx_alcs_send_msg_t) {
|
||||
list_del(&node->linked_list);
|
||||
ALCS_free(node->token);
|
||||
ALCS_free(node->uri);
|
||||
ALCS_free(node);
|
||||
}
|
||||
}
|
||||
|
||||
static void _iotx_alcs_adapter_subdev_list_destroy(iotx_alcs_adapter_t *adapter)
|
||||
{
|
||||
iotx_alcs_send_msg_t *node = NULL;
|
||||
iotx_alcs_send_msg_t *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &adapter->alcs_subdev_list, linked_list, iotx_alcs_send_msg_t) {
|
||||
list_del(&node->linked_list);
|
||||
ALCS_free(node);
|
||||
}
|
||||
}
|
||||
|
||||
int iotx_alcs_adapter_deinit(void)
|
||||
{
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
|
||||
HAL_GetProductKey(product_key);
|
||||
HAL_GetDeviceName(device_name);
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
_iotx_alcs_adapter_send_list_destroy(adapter);
|
||||
_iotx_alcs_adapter_subdev_list_destroy(adapter);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
if (adapter->alcs_event_handle) {
|
||||
ALCS_free(adapter->alcs_event_handle);
|
||||
}
|
||||
|
||||
HAL_MutexDestroy(adapter->mutex);
|
||||
|
||||
alcs_mqtt_deinit(adapter->coap_ctx, product_key, device_name);
|
||||
|
||||
/* if (adapter->coap_ctx) CoAPContext_free(adapter->coap_ctx); */
|
||||
|
||||
alcs_context_deinit();
|
||||
alcs_deinit();
|
||||
alcs_auth_deinit();
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_adapter_init(iotx_alcs_adapter_t *adapter, iotx_alcs_param_t *param)
|
||||
{
|
||||
int res;
|
||||
CoAPInitParam coap_param;
|
||||
CoAPContext *coap_ctx = NULL;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
COAP_INFO("iotx_alcs_adapter_init");
|
||||
memset(&coap_param, 0, sizeof(CoAPInitParam));
|
||||
|
||||
adapter->mutex = HAL_MutexCreate();
|
||||
if (adapter->mutex == NULL) {
|
||||
COAP_ERR("Mutex Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
coap_param.send_maxcount = param->send_maxcount;
|
||||
coap_param.obs_maxcount = param->obs_maxcount;
|
||||
coap_param.port = param->port;
|
||||
coap_param.group = param->group;
|
||||
coap_param.waittime = param->waittime;
|
||||
coap_param.res_maxcount = param->res_maxcount;
|
||||
coap_param.appdata = NULL;
|
||||
coap_param.notifier = iotx_alcs_coap_adapter_event_notifier;
|
||||
|
||||
coap_ctx = alcs_context_init(&coap_param);
|
||||
if (coap_ctx == NULL) {
|
||||
COAP_ERR("Coap Context Init Failed");
|
||||
HAL_MutexDestroy(adapter->mutex);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
adapter->coap_ctx = coap_ctx;
|
||||
|
||||
res = HAL_GetProductKey(product_key);
|
||||
if (res <= 0 || res > IOTX_PRODUCT_KEY_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Product Key Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = HAL_GetDeviceName(device_name);
|
||||
if (res <= 0 || res > IOTX_DEVICE_NAME_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Device Name Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
alcs_init();
|
||||
|
||||
res = alcs_auth_init(coap_ctx, product_key, device_name, param->role);
|
||||
if (res != COAP_SUCCESS) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("ALCS Auth Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
adapter->role = param->role;
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
{
|
||||
extern void on_svr_auth_timer(CoAPContext *);
|
||||
if (adapter->role & IOTX_ALCS_ROLE_SERVER) {
|
||||
adapter->alcs_server_auth_timer_func = on_svr_auth_timer;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
{
|
||||
extern void on_client_auth_timer(CoAPContext *);
|
||||
if (adapter->role & IOTX_ALCS_ROLE_CLIENT) {
|
||||
adapter->alcs_client_auth_timer_func = on_client_auth_timer;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
adapter->alcs_event_handle = (iotx_alcs_event_handle_t *)ALCS_ADAPTER_malloc(sizeof(iotx_alcs_event_handle_t));
|
||||
if (adapter->alcs_event_handle == NULL) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("ALCS Event Handle Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(adapter->alcs_event_handle, param->handle_event, sizeof(iotx_alcs_event_handle_t));
|
||||
|
||||
if (iotx_alcs_adapter_list_init(adapter) != SUCCESS_RETURN) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("ALCS Linked List Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
alcs_localsetup_init(adapter, coap_ctx, product_key, device_name);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static int _iotx_alcs_subdev_list_search(const char *pk, const char *dn, iotx_alcs_subdev_item_t **subdev_item)
|
||||
{
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *node = NULL;
|
||||
|
||||
if (pk == NULL || dn == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
list_for_each_entry(node, &adapter->alcs_subdev_list, linked_list, iotx_alcs_subdev_item_t) {
|
||||
if (strlen(node->product_key) == strlen(pk) &&
|
||||
memcmp(node->product_key, pk, strlen(pk)) == 0 &&
|
||||
strlen(node->device_name) == strlen(dn) &&
|
||||
memcmp(node->device_name, dn, strlen(dn)) == 0) {
|
||||
*subdev_item = node;
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_subdev_remove(const char *pk, const char *dn)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *subdev_item = NULL;
|
||||
|
||||
if (pk == NULL || dn == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_subdev_list_search(pk, dn, &subdev_item);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
COAP_ERR("No Matched Item");
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
list_del(&subdev_item->linked_list);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
ALCS_free(subdev_item);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_subdev_update_stage(iotx_alcs_subdev_item_t *item)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *subdev_item = NULL;
|
||||
|
||||
if (item == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_subdev_list_search(item->product_key, item->device_name, &subdev_item);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
COAP_WRN("No Matched Item");
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
subdev_item->stage = item->stage;
|
||||
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void iotx_alcs_subdev_stage_check(void)
|
||||
{
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *node = NULL;
|
||||
uint64_t time_now = HAL_UptimeMs();
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
list_for_each_entry(node, &adapter->alcs_subdev_list, linked_list, iotx_alcs_subdev_item_t) {
|
||||
if (node->stage == IOTX_ALCS_SUBDEV_DISCONNCET_CLOUD) {
|
||||
if (((time_now > node->retry_ms) &&
|
||||
(time_now - node->retry_ms >= IOTX_ALCS_SUBDEV_RETRY_INTERVAL_MS)) ||
|
||||
((time_now <= node->retry_ms) &&
|
||||
((0xFFFFFFFFFFFFFFFF - node->retry_ms) + time_now >= IOTX_ALCS_SUBDEV_RETRY_INTERVAL_MS))) {
|
||||
/* Get Prefix And Secret From Cloud */
|
||||
alcs_mqtt_subdev_prefix_get(node->product_key, node->device_name);
|
||||
node->retry_ms = time_now;
|
||||
}
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
}
|
||||
|
||||
void *iotx_alcs_construct(iotx_alcs_param_t *params)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
|
||||
COAP_INFO("iotx_alcs_construct enter");
|
||||
|
||||
if (params == NULL || params->group == NULL ||
|
||||
strlen(params->group) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(adapter, 0, sizeof(iotx_alcs_adapter_t));
|
||||
|
||||
res = iotx_alcs_adapter_init(adapter, params);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
COAP_ERR("Adapter Init Failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)adapter;
|
||||
}
|
||||
|
||||
int iotx_alcs_cloud_init(void *handle)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
COAP_INFO("Start ALCS Cloud Init");
|
||||
|
||||
if (adapter->local_cloud_inited == 1) {
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
if (handle == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = HAL_GetProductKey(product_key);
|
||||
if (res <= 0 || res > IOTX_PRODUCT_KEY_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Product Key Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = HAL_GetDeviceName(device_name);
|
||||
if (res <= 0 || res > IOTX_DEVICE_NAME_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Device Name Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (alcs_mqtt_init(adapter->coap_ctx, product_key, device_name) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
/*solve the prpblem of hard fault when mqtt connection fails once*/
|
||||
COAP_ERR("ALCS MQTT Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
adapter->local_cloud_inited = 1;
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_destroy(void **phandle)
|
||||
{
|
||||
if (phandle == NULL || *phandle == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
iotx_alcs_adapter_deinit();
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static void alcs_heartbeat(void *handle)
|
||||
{
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
|
||||
if (adapter->role & IOTX_ALCS_ROLE_SERVER && adapter->alcs_server_auth_timer_func != NULL) {
|
||||
adapter->alcs_server_auth_timer_func(adapter->coap_ctx);
|
||||
}
|
||||
|
||||
if (adapter->role & IOTX_ALCS_ROLE_CLIENT && adapter->alcs_client_auth_timer_func != NULL) {
|
||||
adapter->alcs_client_auth_timer_func(adapter->coap_ctx);
|
||||
}
|
||||
}
|
||||
int iotx_alcs_yield(void *handle)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
alcs_heartbeat(handle);
|
||||
|
||||
iotx_alcs_subdev_stage_check();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int iotx_alcs_send(void *handle, iotx_alcs_msg_t *msg)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
CoAPMessage coap_msg;
|
||||
CoAPLenString coap_payload;
|
||||
NetworkAddr network_addr;
|
||||
|
||||
AlcsDeviceKey devKey;
|
||||
char productKey[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char deviceName[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char *uri_pk = NULL;
|
||||
char *uri_dn = NULL;
|
||||
uint16_t uri_pk_len = 0;
|
||||
uint16_t uri_dn_len = 0;
|
||||
iotx_alcs_send_msg_t *alcs_send_msg = NULL;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx ||
|
||||
msg == NULL || msg->payload == NULL ||
|
||||
msg->ip == NULL || strlen(msg->ip) == 0 ||
|
||||
msg->uri == NULL || strlen(msg->uri) == 0) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (strlen(msg->ip) > NETWORK_ADDR_LEN) {
|
||||
COAP_ERR("Invalid Ip Address Length");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&coap_msg, 0, sizeof(CoAPMessage));
|
||||
memset(&coap_payload, 0, sizeof(CoAPLenString));
|
||||
|
||||
coap_payload.len = msg->payload_len;
|
||||
coap_payload.data = msg->payload;
|
||||
|
||||
alcs_msg_init(adapter->coap_ctx, &coap_msg, msg->msg_code, msg->msg_type, 0, &coap_payload, (void *)adapter);
|
||||
|
||||
res = alcs_msg_setAddr(&coap_msg, msg->uri, NULL);
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Set URI Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&network_addr, 0, sizeof(NetworkAddr));
|
||||
memcpy(network_addr.addr, msg->ip, strlen(msg->ip));
|
||||
network_addr.port = msg->port;
|
||||
|
||||
|
||||
memset(&devKey, 0, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, &network_addr, sizeof(NetworkAddr));
|
||||
|
||||
uri_pk = iotx_alcs_topic_parse_pk(msg->uri, &uri_pk_len);
|
||||
uri_dn = iotx_alcs_topic_parse_dn(msg->uri, &uri_dn_len);
|
||||
|
||||
if (uri_pk == NULL || uri_pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
uri_dn == NULL || uri_dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(productKey, uri_pk, uri_pk_len);
|
||||
memcpy(deviceName, uri_dn, uri_dn_len);
|
||||
|
||||
devKey.pk = productKey;
|
||||
devKey.dn = deviceName;
|
||||
|
||||
res = alcs_sendmsg_secure(adapter->coap_ctx, &devKey, &coap_msg, 2, iotx_alcs_coap_adapter_send_msg_handle);
|
||||
alcs_msg_deinit(&coap_msg);
|
||||
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Send Message Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
alcs_send_msg = (iotx_alcs_send_msg_t *)ALCS_ADAPTER_malloc(sizeof(iotx_alcs_send_msg_t));
|
||||
if (alcs_send_msg == NULL) {
|
||||
COAP_WRN("Not Enough Memory");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(alcs_send_msg, 0, sizeof(iotx_alcs_send_msg_t));
|
||||
|
||||
alcs_send_msg->token = (uint8_t *)ALCS_ADAPTER_malloc(coap_msg.header.tokenlen + 1);
|
||||
if (alcs_send_msg->token == NULL) {
|
||||
ALCS_free(alcs_send_msg);
|
||||
COAP_WRN("Not Enough Memory");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
alcs_send_msg->token_len = coap_msg.header.tokenlen;
|
||||
|
||||
memset(alcs_send_msg->token, 0, alcs_send_msg->token_len + 1);
|
||||
memcpy(alcs_send_msg->token, coap_msg.token, alcs_send_msg->token_len);
|
||||
|
||||
alcs_send_msg->uri = (char *)ALCS_ADAPTER_malloc(strlen(msg->uri) + 1);
|
||||
if (alcs_send_msg->uri == NULL) {
|
||||
ALCS_free(alcs_send_msg->token);
|
||||
ALCS_free(alcs_send_msg);
|
||||
COAP_WRN("ALCS Message Buffer Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(alcs_send_msg->uri, 0, strlen(msg->uri) + 1);
|
||||
memcpy(alcs_send_msg->uri, msg->uri, strlen(msg->uri));
|
||||
INIT_LIST_HEAD(&alcs_send_msg->linked_list);
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
list_add_tail(&alcs_send_msg->linked_list, &adapter->alcs_send_list);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_send_Response(void *handle, iotx_alcs_msg_t *msg, uint8_t token_len, uint8_t *token)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
CoAPMessage coap_msg;
|
||||
CoAPLenString coap_payload;
|
||||
CoAPLenString token_payload;
|
||||
NetworkAddr network_addr;
|
||||
|
||||
AlcsDeviceKey devKey;
|
||||
char productKey[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char deviceName[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char *uri_pk = NULL;
|
||||
char *uri_dn = NULL;
|
||||
uint16_t uri_pk_len = 0;
|
||||
uint16_t uri_dn_len = 0;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx == NULL ||
|
||||
msg == NULL || msg->payload == NULL ||
|
||||
msg->ip == NULL || strlen(msg->ip) == 0 ||
|
||||
msg->uri == NULL || strlen(msg->uri) == 0) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (token_len == 0 || token == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
|
||||
if (strlen(msg->ip) > NETWORK_ADDR_LEN) {
|
||||
COAP_ERR("Invalid Ip Address Length");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&coap_msg, 0, sizeof(CoAPMessage));
|
||||
memset(&coap_payload, 0, sizeof(CoAPLenString));
|
||||
memset(&token_payload, 0, sizeof(CoAPLenString));
|
||||
|
||||
coap_payload.len = msg->payload_len;
|
||||
coap_payload.data = msg->payload;
|
||||
|
||||
alcs_msg_init(adapter->coap_ctx, &coap_msg, msg->msg_code, msg->msg_type, 0, &coap_payload, (void *)adapter);
|
||||
|
||||
res = alcs_msg_setAddr(&coap_msg, msg->uri, NULL);
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Set URI Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&network_addr, 0, sizeof(NetworkAddr));
|
||||
memcpy(network_addr.addr, msg->ip, strlen(msg->ip));
|
||||
network_addr.port = msg->port;
|
||||
|
||||
token_payload.len = token_len;
|
||||
token_payload.data = token;
|
||||
|
||||
memset(&devKey, 0, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, &network_addr, sizeof(NetworkAddr));
|
||||
|
||||
uri_pk = iotx_alcs_topic_parse_pk(msg->uri, &uri_pk_len);
|
||||
uri_dn = iotx_alcs_topic_parse_dn(msg->uri, &uri_dn_len);
|
||||
|
||||
if (uri_pk == NULL || uri_pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
uri_dn == NULL || uri_dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(productKey, uri_pk, uri_pk_len);
|
||||
memcpy(deviceName, uri_dn, uri_dn_len);
|
||||
|
||||
devKey.pk = productKey;
|
||||
devKey.dn = deviceName;
|
||||
|
||||
if (alcs_resource_need_auth(adapter->coap_ctx, msg->uri)) {
|
||||
res = alcs_sendrsp_secure(adapter->coap_ctx, &devKey, &coap_msg, 0, 0, &token_payload);
|
||||
} else {
|
||||
res = alcs_sendrsp(adapter->coap_ctx, &network_addr, &coap_msg, 0, 0, &token_payload);
|
||||
}
|
||||
|
||||
alcs_msg_deinit(&coap_msg);
|
||||
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Send Message Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_register_resource(void *handle, iotx_alcs_res_t *resource)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
char productKey[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char deviceName[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char *uri_pk = NULL;
|
||||
char *uri_dn = NULL;
|
||||
uint16_t uri_pk_len = 0;
|
||||
uint16_t uri_dn_len = 0;
|
||||
int needAuth = 0;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx == NULL ||
|
||||
resource->uri == NULL || strlen(resource->uri) == 0) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
uri_pk = iotx_alcs_topic_parse_pk(resource->uri, &uri_pk_len);
|
||||
uri_dn = iotx_alcs_topic_parse_dn(resource->uri, &uri_dn_len);
|
||||
|
||||
if (uri_pk == NULL || uri_pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
uri_dn == NULL || uri_dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(productKey, uri_pk, uri_pk_len);
|
||||
memcpy(deviceName, uri_dn, uri_dn_len);
|
||||
|
||||
COAP_INFO("alcs register resource, uri:%s", resource->uri);
|
||||
needAuth = resource->need_auth; /* strcmp (resource->uri, "/dev/core/service/dev"); */
|
||||
|
||||
res = alcs_resource_register(adapter->coap_ctx,
|
||||
productKey,
|
||||
deviceName,
|
||||
resource->uri,
|
||||
resource->msg_perm,
|
||||
resource->msg_ct,
|
||||
resource->maxage,
|
||||
needAuth,
|
||||
(void (*)(CoAPContext * context, const char *paths, NetworkAddr * remote,
|
||||
CoAPMessage * message))resource->callback);
|
||||
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Register Resource Failed, Code: %d", res);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_observe_notify(void *handle, const char *uri, uint32_t payload_len, uint8_t *payload)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
CoAPLenString coap_payload;
|
||||
|
||||
coap_payload.len = (int32_t)payload_len;
|
||||
coap_payload.data = payload;
|
||||
|
||||
res = alcs_observe_notify(adapter->coap_ctx, uri, &coap_payload);
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Observe Notify Failed, Code: %d", res);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_unregister_resource(void *handle, char *uri)
|
||||
{
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_add_sub_device(void *handle, const char *pk, const char *dn)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
iotx_alcs_subdev_item_t *subdev_item = NULL;
|
||||
char prefix[ALCS_MQTT_PREFIX_MAX_LEN] = {0};
|
||||
char secret[ALCS_MQTT_SECRET_MAX_LEN] = {0};
|
||||
|
||||
if (handle == NULL || pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Argument");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (adapter->coap_ctx != NULL) {
|
||||
alcs_auth_subdev_init(adapter->coap_ctx, pk, dn);
|
||||
}
|
||||
|
||||
/* Search Subdev In Linked List */
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_subdev_list_search(pk, dn, &subdev_item);
|
||||
if (res == SUCCESS_RETURN) {
|
||||
COAP_INFO("This Product Key And Device Name Have Been Added");
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
/* Insert New Subdev Into Linked List */
|
||||
subdev_item = (iotx_alcs_subdev_item_t *)ALCS_ADAPTER_malloc(sizeof(iotx_alcs_subdev_item_t));
|
||||
if (subdev_item == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(subdev_item, 0, sizeof(iotx_alcs_subdev_item_t));
|
||||
|
||||
/* Set Product Key And Device Name */
|
||||
memcpy(subdev_item->product_key, pk, strlen(pk));
|
||||
memcpy(subdev_item->device_name, dn, strlen(dn));
|
||||
subdev_item->stage = IOTX_ALCS_SUBDEV_DISCONNCET_CLOUD;
|
||||
subdev_item->retry_ms = HAL_UptimeMs();
|
||||
INIT_LIST_HEAD(&subdev_item->linked_list);
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
list_add_tail(&subdev_item->linked_list, &adapter->alcs_subdev_list);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
alcs_localsetup_add_sub_device(adapter, subdev_item->product_key, subdev_item->device_name);
|
||||
|
||||
/* Get Prefix And Secret From KV */
|
||||
res = alcs_mqtt_prefix_secret_load(pk, strlen(pk), dn, strlen(dn), prefix, secret);
|
||||
if (res == SUCCESS_RETURN) {
|
||||
memcpy(subdev_item->prefix, prefix, strlen(prefix));
|
||||
memcpy(subdev_item->secret, secret, strlen(secret));
|
||||
alcs_mqtt_add_srv_key(prefix, secret);
|
||||
}
|
||||
|
||||
/* Get Prefix And Secret From Cloud */
|
||||
alcs_mqtt_subdev_prefix_get(pk, dn);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_remove_sub_device(void *handle, const char *pk, const char *dn)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if (handle == NULL || pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = iotx_alcs_subdev_remove(pk, dn);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Remove Subdev Item From KV */
|
||||
alcs_mqtt_prefix_secret_del(pk, strlen(pk), dn, strlen(dn));
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __ALCS_ADAPTER_H__
|
||||
#define __ALCS_ADAPTER_H__
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "mqtt_api.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "iotx_alcs.h"
|
||||
|
||||
typedef struct iotx_alcs_send_msg_st {
|
||||
uint8_t token_len;
|
||||
uint8_t *token;
|
||||
char *uri;
|
||||
struct list_head linked_list;
|
||||
} iotx_alcs_send_msg_t, *iotx_alcs_send_msg_pt;
|
||||
|
||||
typedef enum {
|
||||
IOTX_ALCS_SUBDEV_DISCONNCET_CLOUD,
|
||||
IOTX_ALCS_SUBDEV_CONNECT_CLOUD
|
||||
} iotx_alcs_subdev_stage_t;
|
||||
|
||||
#define IOTX_ALCS_SUBDEV_RETRY_INTERVAL_MS (10000)
|
||||
|
||||
typedef struct iotx_alcs_subdev_item_st {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char prefix[ALCS_MQTT_PREFIX_MAX_LEN];
|
||||
char secret[ALCS_MQTT_SECRET_MAX_LEN];
|
||||
uint8_t stage;
|
||||
uint64_t retry_ms;
|
||||
struct list_head linked_list;
|
||||
} iotx_alcs_subdev_item_t, *iotx_alcs_subdev_item_pt;
|
||||
|
||||
typedef void (*iotx_alcs_auth_timer_fnuc_t)(CoAPContext *);
|
||||
|
||||
typedef struct iotx_alcs_adapter_st {
|
||||
void *mutex;
|
||||
int local_cloud_inited;
|
||||
CoAPContext *coap_ctx;
|
||||
uint8_t role;
|
||||
iotx_alcs_auth_timer_fnuc_t alcs_client_auth_timer_func;
|
||||
iotx_alcs_auth_timer_fnuc_t alcs_server_auth_timer_func;
|
||||
iotx_alcs_event_handle_t *alcs_event_handle;
|
||||
struct list_head alcs_send_list;
|
||||
struct list_head alcs_subdev_list;
|
||||
char local_ip[NETWORK_ADDR_LEN];
|
||||
uint16_t local_port;
|
||||
} iotx_alcs_adapter_t, *iotx_alcs_adapter_pt;
|
||||
|
||||
int iotx_alcs_subdev_insert(iotx_alcs_subdev_item_t *item);
|
||||
int iotx_alcs_subdev_remove(const char *pk, const char *dn);
|
||||
int iotx_alcs_subdev_search(const char *pk, const char *dn, iotx_alcs_subdev_item_t **item);
|
||||
int iotx_alcs_subdev_update_stage(iotx_alcs_subdev_item_t *item);
|
||||
void iotx_alcs_send_list_handle(void *list_node, va_list *params);
|
||||
int iotx_alcs_adapter_list_init(iotx_alcs_adapter_t *adapter);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,718 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_coap.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPObserve.h"
|
||||
|
||||
ALIYUN_LIST_HEAD(secure_resource_cb_head);
|
||||
|
||||
static bool is_inited = 0;
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
ALIYUN_LIST_HEAD(device_list);
|
||||
|
||||
device_auth_list *get_device(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, &device_list, lst, device_auth_list) {
|
||||
if (node->context == context) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
auth_list *get_list(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *dev_lst = get_device(context);
|
||||
return dev_lst ? &dev_lst->lst_auth : NULL;
|
||||
}
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head *get_ctl_session_list(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *dev_lst = get_device(context);
|
||||
if (!dev_lst || !(dev_lst->role & ROLE_CLIENT)) {
|
||||
return NULL;
|
||||
}
|
||||
return &dev_lst->lst_ctl_sessions;
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head *get_svr_session_list(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *dev_lst = get_device(context);
|
||||
return dev_lst && (dev_lst->role & ROLE_SERVER) ? &dev_lst->lst_svr_sessions : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
device_auth_list _device;
|
||||
#endif
|
||||
|
||||
void remove_session(CoAPContext *ctx, session_item *session)
|
||||
{
|
||||
COAP_INFO("remove_session");
|
||||
if (session) {
|
||||
CoapObsServerAll_delete(ctx, &session->addr);
|
||||
list_del(&session->lst);
|
||||
coap_free(session);
|
||||
}
|
||||
}
|
||||
|
||||
session_item *get_session_by_checksum(struct list_head *sessions, NetworkAddr *addr, char ck[PK_DN_CHECKSUM_LEN])
|
||||
{
|
||||
session_item *node = NULL, *next = NULL;
|
||||
if (!sessions || !ck) {
|
||||
return NULL;
|
||||
}
|
||||
list_for_each_entry_safe(node, next, sessions, lst, session_item) {
|
||||
if (is_networkadd_same(addr, &node->addr)
|
||||
&& strncmp(node->pk_dn, ck, PK_DN_CHECKSUM_LEN) == 0) {
|
||||
COAP_DEBUG("find node, sessionid:%d", node->sessionId);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static session_item *get_session(struct list_head *sessions, AlcsDeviceKey *devKey)
|
||||
{
|
||||
char ck[PK_DN_CHECKSUM_LEN] = {0};
|
||||
char path[100] = {0};
|
||||
if (!sessions || !devKey || !devKey->pk || !devKey->dn) {
|
||||
return NULL;
|
||||
}
|
||||
HAL_Snprintf(path, sizeof(path), "%s%s", devKey->pk, devKey->dn);
|
||||
CoAPPathMD5_sum(path, strlen(path), ck, PK_DN_CHECKSUM_LEN);
|
||||
|
||||
return get_session_by_checksum(sessions, &devKey->addr, ck);
|
||||
}
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
session_item *get_ctl_session(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
struct list_head *sessions = get_ctl_session_list(ctx);
|
||||
COAP_DEBUG("get_ctl_session");
|
||||
return get_session(sessions, devKey);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
session_item *get_svr_session(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
struct list_head *sessions = get_svr_session_list(ctx);
|
||||
return get_session(sessions, devKey);
|
||||
}
|
||||
#endif
|
||||
|
||||
static session_item *get_auth_session(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
session_item *node = get_ctl_session(ctx, devKey);
|
||||
if (node && node->sessionId) {
|
||||
return node;
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
session_item *node1 = get_svr_session(ctx, devKey);
|
||||
if (node1 && node1->sessionId) {
|
||||
return node1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static session_item *get_auth_session_by_checksum(CoAPContext *ctx, NetworkAddr *addr, char ck[])
|
||||
{
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head *sessions = get_ctl_session_list(ctx);
|
||||
session_item *node = get_session_by_checksum(sessions, addr, ck);
|
||||
if (node && node->sessionId) {
|
||||
return node;
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head *sessions1 = get_svr_session_list(ctx);
|
||||
session_item *node1 = get_session_by_checksum(sessions1, addr, ck);
|
||||
if (node1 && node1->sessionId) {
|
||||
return node1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gen_random_key(unsigned char random[], int len)
|
||||
{
|
||||
int i = 0, flag = 0;
|
||||
|
||||
memset(random, 0x00, len);
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
flag = rand() % 3;
|
||||
switch (flag) {
|
||||
case 0:
|
||||
random[i] = 'A' + rand() % 26;
|
||||
break;
|
||||
case 1:
|
||||
random[i] = 'a' + rand() % 26;
|
||||
break;
|
||||
case 2:
|
||||
random[i] = '0' + rand() % 10;
|
||||
break;
|
||||
default:
|
||||
random[i] = 'x';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
extern void alcs_rec_auth_select(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *request);
|
||||
extern void alcs_rec_auth(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *request);
|
||||
extern void alcs_rec_heart_beat(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *request);
|
||||
#endif
|
||||
|
||||
int alcs_auth_init(CoAPContext *ctx, const char *productKey, const char *deviceName, char role)
|
||||
{
|
||||
device_auth_list *dev;
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
char path[256];
|
||||
#endif
|
||||
if (is_inited) {
|
||||
return 0;
|
||||
}
|
||||
is_inited = 1;
|
||||
|
||||
/* auth_list* lst_auth; */
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
|
||||
dev = coap_malloc(sizeof(device_auth_list));
|
||||
list_add_tail(&dev->lst, &device_list);
|
||||
#else
|
||||
dev = &_device;
|
||||
#endif
|
||||
dev->context = ctx;
|
||||
dev->seq = 1;
|
||||
dev->role = role;
|
||||
memset(&dev->lst_auth, 0, sizeof(auth_list));
|
||||
/* strcpy (dev->deviceName, deviceName); */
|
||||
/* strcpy (dev->productKey, productKey); */
|
||||
|
||||
INIT_LIST_HEAD(&dev->lst);
|
||||
INIT_LIST_HEAD(&secure_resource_cb_head);
|
||||
|
||||
if (role & ROLE_SERVER) {
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
INIT_LIST_HEAD(&dev->lst_svr_sessions);
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_svr);
|
||||
|
||||
HAL_Snprintf(path, sizeof(path), "/dev/%s/%s/core/service/auth", productKey, deviceName);
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth);
|
||||
strcat(path, "/select");
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth_select);
|
||||
alcs_resource_register(ctx, productKey, deviceName, "/dev/core/service/heartBeat", COAP_PERM_GET, COAP_CT_APP_JSON, 60,
|
||||
0, alcs_rec_heart_beat);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (role & ROLE_CLIENT) {
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
INIT_LIST_HEAD(&dev->lst_ctl_sessions);
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_ctl);
|
||||
#endif
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_ctl_group);
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_svr_group);
|
||||
dev->lst_auth.list_mutex = HAL_MutexCreate();
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
void alcs_auth_subdev_init(CoAPContext *ctx, const char *productKey, const char *deviceName)
|
||||
{
|
||||
char path[256];
|
||||
HAL_Snprintf(path, sizeof(path), "/dev/%s/%s/core/service/auth", productKey, deviceName);
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth);
|
||||
strcat(path, "/select");
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth_select);
|
||||
}
|
||||
|
||||
void alcs_auth_deinit(void)
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
device_auth_list *node = NULL, *next = NULL;
|
||||
#endif
|
||||
|
||||
alcs_resource_cb_deinit();
|
||||
alcs_auth_list_deinit();
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
list_for_each_entry_safe(node, next, &device_list, lst, device_auth_list) {
|
||||
if (node->lst_auth.list_mutex) {
|
||||
HAL_MutexDestroy(node->lst_auth.list_mutex);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (_device.lst_auth.list_mutex) {
|
||||
HAL_MutexDestroy(_device.lst_auth.list_mutex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_networkadd_same(NetworkAddr *addr1, NetworkAddr *addr2)
|
||||
{
|
||||
if (!addr1 || !addr2) {
|
||||
return 0;
|
||||
}
|
||||
COAP_DEBUG("compare addr1:%s,addr2:%s", addr1->addr, addr2->addr);
|
||||
return addr1->port == addr2->port && !strcmp((const char *)addr1->addr, (const char *)addr2->addr);
|
||||
}
|
||||
|
||||
int alcs_encrypt(const char *src, int len, const char *key, void *out)
|
||||
{
|
||||
char *iv = "a1b1c1d1e1f1g1h1";
|
||||
|
||||
int len1 = len & 0xfffffff0;
|
||||
int len2 = len1 + 16;
|
||||
int pad = len2 - len;
|
||||
int ret = 0;
|
||||
|
||||
if (len1) {
|
||||
p_HAL_Aes128_t aes_e_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_ENCRYPTION);
|
||||
ret = HAL_Aes128_Cbc_Encrypt(aes_e_h, src, len1 >> 4, out);
|
||||
HAL_Aes128_Destroy(aes_e_h);
|
||||
}
|
||||
if (!ret && pad) {
|
||||
char buf[16];
|
||||
p_HAL_Aes128_t aes_e_h = NULL;
|
||||
memcpy(buf, src + len1, len - len1);
|
||||
memset(buf + len - len1, pad, pad);
|
||||
aes_e_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_ENCRYPTION);
|
||||
ret = HAL_Aes128_Cbc_Encrypt(aes_e_h, buf, 1, (uint8_t *)out + len1);
|
||||
HAL_Aes128_Destroy(aes_e_h);
|
||||
}
|
||||
|
||||
COAP_DEBUG("to encrypt src:%s, len:%d", src, len2);
|
||||
return ret == 0 ? len2 : 0;
|
||||
}
|
||||
|
||||
int alcs_decrypt(const char *src, int len, const char *key, void *out)
|
||||
{
|
||||
char *iv = "a1b1c1d1e1f1g1h1";
|
||||
p_HAL_Aes128_t aes_d_h;
|
||||
int n = len >> 4;
|
||||
char *out_c = NULL;
|
||||
int offset = 0;
|
||||
int ret = 0;
|
||||
char pad = 0;
|
||||
|
||||
COAP_DEBUG("to decrypt len:%d", len);
|
||||
|
||||
do {
|
||||
if (n > 1) {
|
||||
aes_d_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_DECRYPTION);
|
||||
if (!aes_d_h) {
|
||||
COAP_ERR("fail to decrypt init");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = HAL_Aes128_Cbc_Decrypt(aes_d_h, src, n - 1, out);
|
||||
HAL_Aes128_Destroy(aes_d_h);
|
||||
|
||||
if (ret != 0) {
|
||||
COAP_ERR("fail to decrypt");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out_c = (char *)out;
|
||||
offset = n > 0 ? ((n - 1) << 4) : 0;
|
||||
out_c[offset] = 0;
|
||||
|
||||
aes_d_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_DECRYPTION);
|
||||
if (!aes_d_h) {
|
||||
COAP_ERR("fail to decrypt init");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = HAL_Aes128_Cbc_Decrypt(aes_d_h, src + offset, 1, out_c + offset);
|
||||
HAL_Aes128_Destroy(aes_d_h);
|
||||
|
||||
if (ret != 0) {
|
||||
COAP_ERR("fail to decrypt remain data");
|
||||
break;
|
||||
}
|
||||
|
||||
pad = out_c[len - 1];
|
||||
out_c[len - pad] = 0;
|
||||
COAP_DEBUG("decrypt data:%s, len:%d", out_c, len - pad);
|
||||
return len - pad;
|
||||
} while (0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool alcs_is_auth(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
return get_auth_session(ctx, devKey) != NULL;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*/
|
||||
typedef struct {
|
||||
void *orig_user_data;
|
||||
char pk_dn[PK_DN_CHECKSUM_LEN];
|
||||
CoAPSendMsgHandler orig_handler;
|
||||
} secure_send_item;
|
||||
|
||||
static int do_secure_send(CoAPContext *ctx, NetworkAddr *addr, CoAPMessage *message, const char *key, char *buf)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
void *payload_old = message->payload;
|
||||
int len_old = message->payloadlen;
|
||||
|
||||
COAP_DEBUG("do_secure_send");
|
||||
|
||||
message->payload = (unsigned char *)buf;
|
||||
message->payloadlen = alcs_encrypt((const char *)payload_old, len_old, key, message->payload);
|
||||
ret = CoAPMessage_send(ctx, addr, message);
|
||||
|
||||
message->payload = payload_old;
|
||||
message->payloadlen = len_old;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void secure_sendmsg_handler(CoAPContext *context, CoAPReqResult result, void *userdata, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
int internal_secure_send(CoAPContext *ctx, session_item *session, NetworkAddr *addr, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler)
|
||||
{
|
||||
int encryptlen = 0;
|
||||
|
||||
COAP_DEBUG("internal_secure_send");
|
||||
if (!ctx || !session || !addr || !message) {
|
||||
COAP_ERR("parameter is null");
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
secure_send_item *item = (secure_send_item *)coap_malloc(sizeof(secure_send_item));
|
||||
item->orig_user_data = message->user;
|
||||
item->orig_handler = handler;
|
||||
memcpy(item->pk_dn, session->pk_dn, PK_DN_CHECKSUM_LEN);
|
||||
|
||||
message->handler = secure_sendmsg_handler;
|
||||
message->user = item;
|
||||
}
|
||||
|
||||
if (observe == 0) {
|
||||
CoAPUintOption_add(message, COAP_OPTION_OBSERVE, observe);
|
||||
}
|
||||
CoAPUintOption_add(message, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_OCTET_STREAM);
|
||||
CoAPUintOption_add(message, COAP_OPTION_SESSIONID, session->sessionId);
|
||||
COAP_DEBUG("secure_send sessionId:%d", session->sessionId);
|
||||
|
||||
encryptlen = (message->payloadlen & 0xfffffff0) + 16;
|
||||
if (encryptlen > 64) {
|
||||
char *buf = (char *)coap_malloc(encryptlen);
|
||||
int rt = do_secure_send(ctx, addr, message, session->sessionKey, buf);
|
||||
coap_free(buf);
|
||||
return rt;
|
||||
} else {
|
||||
char buf[64];
|
||||
return do_secure_send(ctx, addr, message, session->sessionKey, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_cb(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message, const char *key, char *buf,
|
||||
secure_send_item *send_item)
|
||||
{
|
||||
if (send_item->orig_handler) {
|
||||
int len = alcs_decrypt((const char *)message->payload, message->payloadlen, key, buf);
|
||||
CoAPMessage tmpMsg;
|
||||
memcpy(&tmpMsg, message, sizeof(CoAPMessage));
|
||||
tmpMsg.payload = (unsigned char *)buf;
|
||||
tmpMsg.payloadlen = len;
|
||||
send_item->orig_handler(context, COAP_REQUEST_SUCCESS, send_item->orig_user_data, remote, &tmpMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void secure_sendmsg_handler(CoAPContext *context, CoAPReqResult result, void *userdata, NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
secure_send_item *send_item = (secure_send_item *)userdata;
|
||||
session_item *session = NULL;
|
||||
unsigned int obsVal;
|
||||
|
||||
if (!context || !userdata || !remote) {
|
||||
return;
|
||||
}
|
||||
if (result == COAP_RECV_RESP_TIMEOUT) {
|
||||
if (send_item->orig_handler) {
|
||||
send_item->orig_handler(context, COAP_RECV_RESP_TIMEOUT, send_item->orig_user_data, remote, NULL);
|
||||
}
|
||||
COAP_INFO("secure_sendmsg_handler timeout");
|
||||
} else {
|
||||
unsigned int sessionId = 0;
|
||||
CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
|
||||
COAP_DEBUG("secure_sendmsg_handler, sessionID:%d", (int)sessionId);
|
||||
|
||||
session = get_auth_session_by_checksum(context, remote, send_item->pk_dn);
|
||||
|
||||
if (!session || session->sessionId != sessionId) {
|
||||
COAP_ERR("secure_sendmsg_handler, need auth, from:%s", remote->addr);
|
||||
/* todo */
|
||||
} else {
|
||||
session->heart_time = HAL_UptimeMs();
|
||||
if (message->payloadlen < 128) {
|
||||
char buf[128];
|
||||
call_cb(context, remote, message, session->sessionKey, buf, send_item);
|
||||
} else {
|
||||
char *buf = (char *)coap_malloc(message->payloadlen);
|
||||
if (buf) {
|
||||
call_cb(context, remote, message, session->sessionKey, buf, send_item);
|
||||
coap_free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &obsVal) != COAP_SUCCESS) {
|
||||
coap_free(send_item);
|
||||
}
|
||||
}
|
||||
|
||||
int alcs_sendmsg_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler)
|
||||
{
|
||||
session_item *session = NULL;
|
||||
|
||||
if (!ctx || !devKey || !message) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
session = get_auth_session(ctx, devKey);
|
||||
if (!session) {
|
||||
COAP_DEBUG("alcs_sendmsg_secure, session not found");
|
||||
return ALCS_ERR_AUTH_UNAUTH;
|
||||
}
|
||||
|
||||
return internal_secure_send(ctx, session, &devKey->addr, message, observe, handler);
|
||||
}
|
||||
|
||||
int alcs_sendrsp_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
unsigned short msgid, CoAPLenString *token)
|
||||
{
|
||||
session_item *session = NULL;
|
||||
|
||||
COAP_DEBUG("alcs_sendrsp_secure");
|
||||
if (!ctx || !devKey || !message) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (msgid == 0) {
|
||||
message->header.msgid = CoAPMessageId_gen(ctx);
|
||||
} else {
|
||||
message->header.msgid = msgid;
|
||||
}
|
||||
|
||||
if (token) {
|
||||
message->header.tokenlen = token->len;
|
||||
memcpy(&message->token, token->data, token->len);
|
||||
}
|
||||
|
||||
session = get_auth_session(ctx, devKey);
|
||||
if (!session) {
|
||||
COAP_DEBUG("alcs_sendrsp_secure, session not found");
|
||||
return ALCS_ERR_AUTH_UNAUTH;
|
||||
}
|
||||
|
||||
return internal_secure_send(ctx, session, &devKey->addr, message, observe, NULL);
|
||||
}
|
||||
|
||||
bool req_payload_parser(const char *payload, int len, char **seq, int *seqlen, char **data, int *datalen)
|
||||
{
|
||||
if (!payload || !len || !seq || !seqlen || !datalen || !data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*seq = json_get_value_by_name((char *)payload, len, "id", seqlen, NULL);
|
||||
|
||||
*data = json_get_value_by_name((char *)payload, len, "params", datalen, NULL);
|
||||
return *data && datalen;
|
||||
}
|
||||
|
||||
void on_auth_timer(void *param)
|
||||
{
|
||||
CoAPContext *ctx = NULL;
|
||||
if (!is_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = (CoAPContext *) param;
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
{
|
||||
extern void on_client_auth_timer(CoAPContext *);
|
||||
on_client_auth_timer(ctx);
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
{
|
||||
extern void on_svr_auth_timer(CoAPContext *);
|
||||
on_svr_auth_timer(ctx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int alcs_add_ctl_group(CoAPContext *context, const char *groupid, const char *accesskey, const char *accesstoken)
|
||||
{
|
||||
ctl_group_item *item = NULL;
|
||||
auth_list *lst = get_list(context);
|
||||
if (!lst || lst->ctl_group_count >= KEY_MAXCOUNT) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
item = (ctl_group_item *) coap_malloc(sizeof(ctl_group_item));
|
||||
if (!item) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
memset(item, 0, sizeof(ctl_group_item));
|
||||
|
||||
do {
|
||||
item->id = (char *) coap_malloc(strlen(groupid) + 1);
|
||||
if (!item->id) {
|
||||
break;
|
||||
}
|
||||
|
||||
item->accessKey = (char *) coap_malloc(strlen(accesskey) + 1);
|
||||
if (!item->accessKey) {
|
||||
break;
|
||||
}
|
||||
|
||||
item->accessToken = (char *) coap_malloc(strlen(accesstoken) + 1);
|
||||
if (!item->accessToken) {
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(item->accessKey, accesskey);
|
||||
strcpy(item->accessToken, accesstoken);
|
||||
strcpy(item->id, groupid);
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
list_add_tail(&item->lst, &lst->lst_ctl_group);
|
||||
++lst->ctl_group_count;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (item->id) {
|
||||
coap_free(item->id);
|
||||
}
|
||||
if (item->accessKey) {
|
||||
coap_free(item->accessKey);
|
||||
}
|
||||
if (item->accessToken) {
|
||||
coap_free(item->accessToken);
|
||||
}
|
||||
coap_free(item);
|
||||
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
int alcs_remove_ctl_group(CoAPContext *context, const char *groupid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alcs_add_svr_group(CoAPContext *context, const char *groupid, const char *keyprefix, const char *secret)
|
||||
{
|
||||
svr_group_item *item = NULL;
|
||||
auth_list *lst = get_list(context);
|
||||
if (!lst || lst->svr_group_count >= KEY_MAXCOUNT) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
item = (svr_group_item *) coap_malloc(sizeof(svr_group_item));
|
||||
if (!item) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
memset(item, 0, sizeof(svr_group_item));
|
||||
|
||||
do {
|
||||
item->id = (char *) coap_malloc(strlen(groupid) + 1);
|
||||
if (!item->id) {
|
||||
break;
|
||||
}
|
||||
|
||||
item->keyInfo.secret = (char *) coap_malloc(strlen(secret) + 1);
|
||||
if (!item->keyInfo.secret) {
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(item->keyInfo.keyprefix, keyprefix, sizeof(item->keyInfo.keyprefix) - 1);
|
||||
strcpy(item->keyInfo.secret, secret);
|
||||
strcpy(item->id, groupid);
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
list_add_tail(&item->lst, &lst->lst_svr_group);
|
||||
++lst->svr_group_count;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (item->id) {
|
||||
coap_free(item->id);
|
||||
}
|
||||
if (item->keyInfo.secret) {
|
||||
coap_free(item->keyInfo.secret);
|
||||
}
|
||||
coap_free(item);
|
||||
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
int alcs_remove_svr_group(CoAPContext *context, const char *groupid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void alcs_utils_md5_hexstr(unsigned char input[16], unsigned char output[32])
|
||||
{
|
||||
unsigned char idx = 0;
|
||||
unsigned char output_char = 0;
|
||||
|
||||
for (idx = 0; idx < 16; idx++) {
|
||||
if (((input[idx] >> 4) & 0x0F) <= 0x09) {
|
||||
output_char = ((input[idx] >> 4) & 0x0F) + '0';
|
||||
} else if (((input[idx] >> 4) & 0x0F) >= 0x0A) {
|
||||
output_char = ((input[idx] >> 4) & 0x0F) + 'a' - 0x0A;
|
||||
}
|
||||
output[2 * idx] = output_char;
|
||||
|
||||
if (((input[idx]) & 0x0F) <= 0x09) {
|
||||
output_char = ((input[idx]) & 0x0F) + '0';
|
||||
} else if (((input[idx]) & 0x0F) >= 0x0A) {
|
||||
output_char = ((input[idx]) & 0x0F) + 'a' - 0x0A;
|
||||
}
|
||||
output[2 * idx + 1] = output_char;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "alcs_coap.h"
|
||||
|
||||
#ifndef __ALCS_API_H__
|
||||
#define __ALCS_API_H__
|
||||
|
||||
#define SESSIONID_LEN 8
|
||||
#define SESSIONKEY_MAXLEN 30
|
||||
|
||||
#define ALCS_ERR_AUTH_BASE (COAP_ERROR_BASE | 100)
|
||||
#define ALCS_ERR_AUTH_AUTHING (ALCS_ERR_AUTH_BASE | 1)
|
||||
#define ALCS_ERR_AUTH_NOCTLKEY (ALCS_ERR_AUTH_BASE | 2)
|
||||
#define ALCS_ERR_AUTH_UNAUTH (ALCS_ERR_AUTH_BASE | 3)
|
||||
#define ALCS_ERR_ENCRYPT_FAILED (ALCS_ERR_AUTH_BASE | 5)
|
||||
|
||||
typedef enum {
|
||||
ALCS_AUTH_OK = 200,
|
||||
ALCS_AUTH_REVOCATE = 501,
|
||||
ALCS_AUTH_UNMATCHPREFIX,
|
||||
ALCS_AUTH_INVALIDPARAM,
|
||||
ALCS_AUTH_AUTHLISTEMPTY,
|
||||
ALCS_AUTH_VERNOTSUPPORT,
|
||||
ALCS_AUTH_ILLEGALSIGN,
|
||||
ALCS_HEART_FAILAUTH,
|
||||
} Auth_Result_Code;
|
||||
|
||||
#include "iotx_alcs_config.h"
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
char *msg;/* MUST call coap_free to free memory */
|
||||
} ResponseMsg;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
ResponseMsg msg;
|
||||
char sessionId [SESSIONID_LEN];
|
||||
char sessionKey[SESSIONKEY_MAXLEN];
|
||||
NetworkAddr addr;
|
||||
} AuthResult;
|
||||
*/
|
||||
|
||||
typedef void (*AuthHandler)(CoAPContext *context, NetworkAddr *addr, void *user_data, ResponseMsg *result);
|
||||
typedef struct {
|
||||
char *productKey;
|
||||
char *deviceName;
|
||||
char *accessKey;
|
||||
char *accessToken;
|
||||
void *user_data;
|
||||
AuthHandler handler;
|
||||
} AuthParam;
|
||||
|
||||
typedef struct {
|
||||
NetworkAddr addr;
|
||||
char *pk;
|
||||
char *dn;
|
||||
} AlcsDeviceKey;
|
||||
|
||||
/* 初始化认证模块
|
||||
* context: 为当前设备生成的CoAPContext对象指针
|
||||
* productKey:当前设备的productKey,可以为空
|
||||
* deviceName: 当前设备的deviceName,可以为空
|
||||
* role: 1 --client
|
||||
* 2 --server
|
||||
* 3 --client&server
|
||||
*/
|
||||
int alcs_auth_init(CoAPContext *context, const char *productKey, const char *deviceName, char role);
|
||||
void alcs_auth_subdev_init(CoAPContext *ctx, const char *productKey, const char *deviceName);
|
||||
void alcs_auth_deinit(void);
|
||||
|
||||
bool alcs_is_auth(CoAPContext *ctx, AlcsDeviceKey *devKey);
|
||||
int alcs_sendmsg_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler);
|
||||
int alcs_sendrsp_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
unsigned short msgid, CoAPLenString *token);
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
/* 身份认证-- 直接传入accesskey&accesstoken
|
||||
* context: 当前设备生成的CoAPContext对象指针
|
||||
* addr: 待连设备地址
|
||||
* auth_param:包含待连设备的信息和回调接口
|
||||
*/
|
||||
void alcs_auth_has_key(CoAPContext *ctx, NetworkAddr *addr, AuthParam *auth_param);
|
||||
|
||||
/* 身份认证--通过productkey&devicename在缓存的accesskey列表中查找合适accesskey
|
||||
* 此函数需要和alcs_add_client_key 配合使用
|
||||
* 若不知道准确的accessKey,认证前client会和server协商合适的accessKey
|
||||
*
|
||||
* context: 为当前设备生成的CoAPContext对象指针
|
||||
* addr: 待连设备地址
|
||||
* productKey:待连设备的productKey
|
||||
* deviceName:待连设备的deviceName
|
||||
* handler: 结果回调接口
|
||||
*/
|
||||
void alcs_auth_nego_key(CoAPContext *ctx, AlcsDeviceKey *devKey, AuthHandler handler);
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
int alcs_add_client_key(CoAPContext *context, const char *accesskey, const char *accesstoken, const char *productKey,
|
||||
const char *deviceName);
|
||||
int alcs_remove_client_key(CoAPContext *context, const char *key, char isfullkey);
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
bool alcs_device_online(CoAPContext *context, AlcsDeviceKey *devKey);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
typedef enum {
|
||||
LOCALDEFAULT,
|
||||
LOCALSETUP,
|
||||
FROMCLOUDSVR
|
||||
} ServerKeyPriority;
|
||||
|
||||
int alcs_add_svr_key(CoAPContext *context, const char *keyprefix, const char *secret, ServerKeyPriority priority);
|
||||
int alcs_remove_svr_key(CoAPContext *context, const char *keyprefix);
|
||||
/* 设置吊销列表*
|
||||
* context: 为当前设备生成的CoAPContext对象指针
|
||||
* seqlist: 吊销列表字符串,每个被吊销设备占用三字节
|
||||
*/
|
||||
int alcs_set_revocation(CoAPContext *context, const char *seqlist);
|
||||
#endif
|
||||
|
||||
int alcs_add_ctl_group(CoAPContext *context, const char *groupid, const char *accesskey, const char *accesstoken);
|
||||
int alcs_remove_ctl_group(CoAPContext *context, const char *groupid);
|
||||
|
||||
int alcs_add_svr_group(CoAPContext *context, const char *groupid, const char *keyprefix, const char *secret);
|
||||
int alcs_remove_svr_group(CoAPContext *context, const char *groupid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __ALCS_API_INTERNAL_H__
|
||||
#define __ALCS_API_INTERNAL_H__
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_internal.h"
|
||||
|
||||
#define KEY_MAXCOUNT 10
|
||||
#define RANDOMKEY_LEN 16
|
||||
#define KEYSEQ_LEN 3
|
||||
#define COAP_OPTION_SESSIONID 71
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
typedef struct {
|
||||
char *accessKey;
|
||||
char *accessToken;
|
||||
char *deviceName;
|
||||
char *productKey;
|
||||
struct list_head lst;
|
||||
} ctl_key_item;
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
|
||||
typedef struct {
|
||||
char keyprefix[KEYPREFIX_LEN + 1];
|
||||
char *secret;
|
||||
ServerKeyPriority priority;
|
||||
} svr_key_info;
|
||||
|
||||
typedef struct {
|
||||
svr_key_info keyInfo;
|
||||
struct list_head lst;
|
||||
} svr_key_item;
|
||||
|
||||
typedef struct {
|
||||
char *id;
|
||||
char *revocation;
|
||||
svr_key_info keyInfo;
|
||||
struct list_head lst;
|
||||
} svr_group_item;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *id;
|
||||
char *accessKey;
|
||||
char *accessToken;
|
||||
struct list_head lst;
|
||||
} ctl_group_item;
|
||||
|
||||
typedef struct {
|
||||
void *list_mutex;
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head lst_ctl;
|
||||
unsigned char ctl_count;
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head lst_svr;
|
||||
unsigned char svr_count;
|
||||
char *revocation;
|
||||
#endif
|
||||
struct list_head lst_ctl_group;
|
||||
int ctl_group_count;
|
||||
struct list_head lst_svr_group;
|
||||
int svr_group_count;
|
||||
} auth_list;
|
||||
|
||||
#define PK_DN_CHECKSUM_LEN 6
|
||||
typedef struct {
|
||||
char randomKey[RANDOMKEY_LEN + 1];
|
||||
int sessionId;
|
||||
char sessionKey[32];
|
||||
int authed_time;
|
||||
int heart_time;
|
||||
int interval;
|
||||
NetworkAddr addr;
|
||||
char pk_dn[PK_DN_CHECKSUM_LEN];
|
||||
struct list_head lst;
|
||||
} session_item;
|
||||
|
||||
#define ROLE_SERVER 2
|
||||
#define ROLE_CLIENT 1
|
||||
|
||||
typedef struct {
|
||||
CoAPContext *context;
|
||||
int seq;
|
||||
auth_list lst_auth;
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head lst_svr_sessions;
|
||||
#endif
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head lst_ctl_sessions;
|
||||
#endif
|
||||
char role;
|
||||
struct list_head lst;
|
||||
} device_auth_list;
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
extern struct list_head device_list;
|
||||
|
||||
device_auth_list *get_device(CoAPContext *context);
|
||||
|
||||
auth_list *get_list(CoAPContext *context);
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head *get_ctl_session_list(CoAPContext *context);
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head *get_svr_session_list(CoAPContext *context);
|
||||
#endif
|
||||
|
||||
#else
|
||||
extern device_auth_list _device;
|
||||
#define get_device(v) (&_device)
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
#define get_svr_session_list(v) (_device.role&ROLE_SERVER? &_device.lst_svr_sessions : NULL)
|
||||
#endif
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
#define get_ctl_session_list(v) (_device.role&ROLE_CLIENT? &_device.lst_ctl_sessions : NULL)
|
||||
#endif
|
||||
|
||||
#define get_list(v) (&_device.lst_auth)
|
||||
#endif
|
||||
|
||||
void remove_session(CoAPContext *ctx, session_item *session);
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
session_item *get_ctl_session(CoAPContext *ctx, AlcsDeviceKey *key);
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
session_item *get_svr_session(CoAPContext *ctx, AlcsDeviceKey *key);
|
||||
session_item *get_session_by_checksum(struct list_head *sessions, NetworkAddr *addr, char ck[PK_DN_CHECKSUM_LEN]);
|
||||
|
||||
#define MAX_PATH_CHECKSUM_LEN (5)
|
||||
typedef struct {
|
||||
char path[MAX_PATH_CHECKSUM_LEN];
|
||||
char pk_dn[PK_DN_CHECKSUM_LEN];
|
||||
char *filter_path;
|
||||
path_type_t path_type;
|
||||
CoAPRecvMsgHandler cb;
|
||||
struct list_head lst;
|
||||
} secure_resource_cb_item;
|
||||
|
||||
extern struct list_head secure_resource_cb_head;
|
||||
#endif
|
||||
|
||||
int alcs_encrypt(const char *src, int len, const char *key, void *out);
|
||||
int alcs_decrypt(const char *src, int len, const char *key, void *out);
|
||||
int observe_data_encrypt(CoAPContext *ctx, const char *paths, NetworkAddr *addr,
|
||||
CoAPMessage *message, CoAPLenString *src, CoAPLenString *dest);
|
||||
|
||||
bool is_networkadd_same(NetworkAddr *addr1, NetworkAddr *addr2);
|
||||
void gen_random_key(unsigned char random[], int len);
|
||||
bool req_payload_parser(const char *payload, int len, char **seq, int *seqlen, char **data, int *datalen);
|
||||
int internal_secure_send(CoAPContext *ctx, session_item *session, NetworkAddr *addr,
|
||||
CoAPMessage *message, char observe, CoAPSendMsgHandler handler);
|
||||
|
||||
int alcs_resource_register_secure(CoAPContext *context, const char *pk, const char *dn, const char *path,
|
||||
unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage, CoAPRecvMsgHandler callback);
|
||||
void alcs_resource_cb_deinit(void);
|
||||
void alcs_auth_list_deinit(void);
|
||||
void alcs_utils_md5_hexstr(unsigned char input[16], unsigned char output[32]);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "alcs_base64.h"
|
||||
|
||||
static int8_t g_encodingTable[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
static int8_t g_decodingTable[256];
|
||||
static int32_t g_modTable[] = { 0, 2, 1 };
|
||||
|
||||
static void build_decoding_table()
|
||||
{
|
||||
static int32_t signal = 0;
|
||||
int32_t i = 0;
|
||||
|
||||
if (signal != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
g_decodingTable[(uint8_t) g_encodingTable[i]] = i;
|
||||
}
|
||||
|
||||
signal = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
int utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *encodedData, uint32_t *outputLength)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
|
||||
if (NULL == encodedData) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*outputLength = 4 * ((inputLength + 2) / 3);
|
||||
|
||||
if (outputLenMax < *outputLength) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < inputLength;) {
|
||||
uint32_t octet_a = i < inputLength ? (uint8_t) data[i++] : 0;
|
||||
uint32_t octet_b = i < inputLength ? (uint8_t) data[i++] : 0;
|
||||
uint32_t octet_c = i < inputLength ? (uint8_t) data[i++] : 0;
|
||||
|
||||
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||
|
||||
encodedData[j++] = g_encodingTable[(triple >> 3 * 6) & 0x3F];
|
||||
encodedData[j++] = g_encodingTable[(triple >> 2 * 6) & 0x3F];
|
||||
encodedData[j++] = g_encodingTable[(triple >> 1 * 6) & 0x3F];
|
||||
encodedData[j++] = g_encodingTable[(triple >> 0 * 6) & 0x3F];
|
||||
}
|
||||
|
||||
for (i = 0; i < g_modTable[inputLength % 3]; i++) {
|
||||
encodedData[*outputLength - 1 - i] = '=';
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *decodedData, uint32_t *outputLength)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
uint32_t sextet_a = 0;
|
||||
uint32_t sextet_b = 0;
|
||||
uint32_t sextet_c = 0;
|
||||
uint32_t sextet_d = 0;
|
||||
uint32_t triple = 0;
|
||||
|
||||
build_decoding_table();
|
||||
|
||||
if (inputLength % 4 != 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*outputLength = inputLength / 4 * 3;
|
||||
|
||||
|
||||
if (data[inputLength - 1] == '=') {
|
||||
(*outputLength)--;
|
||||
}
|
||||
|
||||
if (data[inputLength - 2] == '=') {
|
||||
(*outputLength)--;
|
||||
}
|
||||
|
||||
if (outputLenMax < *outputLength) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < inputLength;) {
|
||||
sextet_a = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
sextet_b = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
sextet_c = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
sextet_d = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
|
||||
triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
|
||||
|
||||
if (j < *outputLength) {
|
||||
decodedData[j++] = (triple >> 2 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
if (j < *outputLength) {
|
||||
decodedData[j++] = (triple >> 1 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
if (j < *outputLength) {
|
||||
decodedData[j++] = (triple >> 0 * 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _ALCS_BASE64_H_
|
||||
#define _ALCS_BASE64_H_
|
||||
|
||||
#include "infra_types.h"
|
||||
|
||||
int utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *encodedData, uint32_t *outputLength);
|
||||
int utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *decodedData, uint32_t *outputLength);
|
||||
#endif
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPResource.h"
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
static int default_heart_interval = 30000;
|
||||
char match_key(const char *accesskey, const char *keyprefix)
|
||||
{
|
||||
if (strlen(keyprefix) == KEYPREFIX_LEN && strstr(accesskey, keyprefix) == accesskey) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_auth(CoAPContext *ctx, NetworkAddr *addr, ctl_key_item *ctl_item, void *userdata, AuthHandler handler);
|
||||
bool res_parse(const char *payload, int len, int *seq, ResponseMsg *res_msg, char **data, int *datalen)
|
||||
{
|
||||
if (!payload || !len || !seq || !res_msg || !data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
COAP_DEBUG("payload:%.*s", len, payload);
|
||||
|
||||
int tmplen;
|
||||
char *tmp;
|
||||
|
||||
tmp = json_get_value_by_name((char *)payload, len, "id", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char back;
|
||||
backup_json_str_last_char(tmp, tmplen, back);
|
||||
*seq = atoi(tmp);
|
||||
restore_json_str_last_char(tmp, tmplen, back);
|
||||
|
||||
tmp = json_get_value_by_name((char *)payload, len, "code", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
backup_json_str_last_char(tmp, tmplen, back);
|
||||
res_msg->code = atoi(tmp);
|
||||
restore_json_str_last_char(tmp, tmplen, back);
|
||||
|
||||
tmp = json_get_value_by_name((char *)payload, len, "msg", &tmplen, NULL);
|
||||
if (tmp && tmplen) {
|
||||
res_msg->msg = (char *)coap_malloc(tmplen);
|
||||
memcpy(res_msg->msg, tmp, tmplen);
|
||||
} else {
|
||||
res_msg->msg = NULL;
|
||||
}
|
||||
|
||||
*data = json_get_value_by_name((char *)payload, len, "data", datalen, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool fillAccessKey(CoAPContext *ctx, char *buf)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
if (!lst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
if (list_empty(&lst->lst_ctl)) {
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return 0;
|
||||
}
|
||||
strcpy(buf, ",\"accessKeys\":[");
|
||||
ctl_key_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item) {
|
||||
char *format;
|
||||
if (lst->ctl_group_count || !list_is_last(&node->lst, &lst->lst_ctl)) {
|
||||
format = "\"%s\",";
|
||||
} else {
|
||||
format = "\"%s\"]";
|
||||
}
|
||||
sprintf(buf + strlen(buf), format, node->accessKey);
|
||||
}
|
||||
|
||||
ctl_group_item *gnode = NULL, *gnext = NULL;
|
||||
list_for_each_entry_safe(gnode, gnext, &lst->lst_ctl_group, lst, ctl_group_item) {
|
||||
char *format;
|
||||
if (!list_is_last(&gnode->lst, &lst->lst_ctl_group)) {
|
||||
format = "\"%s\",";
|
||||
} else {
|
||||
format = "\"%s\"]";
|
||||
}
|
||||
sprintf(buf + strlen(buf), format, gnode->accessKey);
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define payload_format "{\"version\":\"1.0\",\"method\":\"%s\",\"id\":%d,\"params\":{\"prodKey\":\"%s\", \"deviceName\":\"%s\"%s}}"
|
||||
void nego_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
COAP_INFO("nego_cb, message addr:%p, networkaddr:%p!", message, remote);
|
||||
AuthParam *auth_param = (AuthParam *)userdata;
|
||||
|
||||
if (COAP_RECV_RESP_TIMEOUT == result) {
|
||||
ResponseMsg msg = {-1, "response time!"};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param);
|
||||
|
||||
} else {
|
||||
COAP_DEBUG("recv response message");
|
||||
int seq, datalen;
|
||||
ResponseMsg msg;
|
||||
char *data;
|
||||
|
||||
res_parse((const char *)message->payload, message->payloadlen, &seq, &msg, &data, &datalen);
|
||||
do {
|
||||
if (msg.code != 200) {
|
||||
break;
|
||||
}
|
||||
|
||||
int keylen;
|
||||
char *accessKey = json_get_value_by_name(data, datalen, "accessKey", &keylen, NULL);
|
||||
if (!accessKey || !keylen) {
|
||||
break;
|
||||
}
|
||||
COAP_DEBUG("accesskey:%.*s", keylen, accessKey);
|
||||
|
||||
auth_list *lst = get_list(ctx);
|
||||
ctl_key_item *node = NULL, *next = NULL;
|
||||
char *accessTokenFound = NULL;
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item) {
|
||||
COAP_DEBUG("node:%s", node->accessKey);
|
||||
if (strncmp(node->accessKey, accessKey, keylen) == 0) {
|
||||
accessTokenFound = node->accessToken;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!accessTokenFound) {
|
||||
ctl_group_item *gnode = NULL, *gnext = NULL;
|
||||
list_for_each_entry_safe(gnode, gnext, &lst->lst_ctl_group, lst, ctl_group_item) {
|
||||
COAP_DEBUG("node:%s", gnode->accessKey);
|
||||
if (strncmp(gnode->accessKey, accessKey, keylen) == 0) {
|
||||
accessTokenFound = gnode->accessKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
if (accessTokenFound) {
|
||||
ctl_key_item item;
|
||||
item.deviceName = auth_param->deviceName;
|
||||
item.productKey = auth_param->productKey;
|
||||
|
||||
item.accessKey = accessKey;
|
||||
item.accessToken = accessTokenFound;
|
||||
char back;
|
||||
backup_json_str_last_char(accessKey, keylen, back);
|
||||
do_auth(ctx, remote, &item, auth_param->user_data, auth_param->handler);
|
||||
restore_json_str_last_char(accessKey, keylen, back);
|
||||
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param);
|
||||
return;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
/* todo */
|
||||
ResponseMsg tmp = {-1, ""};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &tmp);
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int CoAPServerPath_2_option(char *uri, CoAPMessage *message)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
char *pstr = NULL;
|
||||
char path[COAP_MSG_MAX_PATH_LEN] = {0};
|
||||
|
||||
if (NULL == uri || NULL == message) {
|
||||
COAP_ERR("Invalid paramter p_path %p, p_message %p", uri, message);
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (256 < strlen(uri)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
COAP_DEBUG("The uri is %s", uri);
|
||||
ptr = pstr = uri;
|
||||
while ('\0' != *ptr) {
|
||||
if ('/' == *ptr) {
|
||||
if (ptr != pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, ptr - pstr);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)(ptr - pstr));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
pstr = ptr + 1;
|
||||
|
||||
}
|
||||
if ('\0' == *(ptr + 1) && '\0' != *pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, sizeof(path) - 1);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)strlen(path));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
ptr ++;
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
void auth_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
AlcsDeviceKey devKey;
|
||||
COAP_DEBUG("recv auth_cb response message");
|
||||
|
||||
AuthParam *auth_param = (AuthParam *)userdata;
|
||||
memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, remote, sizeof(NetworkAddr));
|
||||
devKey.pk = auth_param->productKey;
|
||||
devKey.dn = auth_param->deviceName;
|
||||
session_item *session = get_ctl_session(ctx, &devKey);
|
||||
|
||||
if (!session) {
|
||||
COAP_INFO("receive unknown auth_cb response, pk:%s, dn:%s", devKey.pk, devKey.dn);
|
||||
ResponseMsg msg = {-1, "no session found!"};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
} else if (COAP_RECV_RESP_TIMEOUT == result) {
|
||||
COAP_ERR("response time!");
|
||||
ResponseMsg msg = {-1, "response time!"};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
remove_session(ctx, session);
|
||||
} else {
|
||||
int seq, datalen;
|
||||
ResponseMsg msg;
|
||||
char *data;
|
||||
|
||||
res_parse((const char *)message->payload, message->payloadlen, &seq, &msg, &data, &datalen);
|
||||
if (msg.code == 200) {
|
||||
do {
|
||||
int tmplen;
|
||||
char *tmp;
|
||||
|
||||
tmp = json_get_value_by_name(data, datalen, "sessionId", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
msg.code = -1;
|
||||
msg.msg = "sessionid = NULL!";
|
||||
COAP_ERR("sessionid = NULL!");
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
break;
|
||||
}
|
||||
char back;
|
||||
backup_json_str_last_char(tmp, tmplen, back);
|
||||
session->sessionId = atoi(tmp);
|
||||
restore_json_str_last_char(tmp, tmplen, back);
|
||||
COAP_INFO("sessionId:%d", session->sessionId);
|
||||
|
||||
tmp = json_get_value_by_name(data, datalen, "randomKey", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
msg.code = -1;
|
||||
msg.msg = "randomKey = NULL!";
|
||||
COAP_ERR("randomKey = NULL!");
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
break;
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
HAL_Snprintf(buf, sizeof(buf), "%s%.*s", session->randomKey, tmplen, tmp);
|
||||
utils_hmac_sha1_hex(buf, strlen(buf), session->sessionKey, auth_param->accessToken, strlen(auth_param->accessToken));
|
||||
session->authed_time = HAL_UptimeMs();
|
||||
session->heart_time = session->authed_time;
|
||||
session->interval = default_heart_interval;
|
||||
COAP_INFO("sessionKey is created");
|
||||
} while (0);
|
||||
} else {
|
||||
remove_session(ctx, session);
|
||||
COAP_ERR("message code :%d", msg.code);
|
||||
}
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
}
|
||||
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param->accessToken);
|
||||
coap_free(auth_param);
|
||||
}
|
||||
|
||||
#define auth_payload_format "{\"version\":\"1.0\",\"method\":\"core/service/auth\",\"id\":%d,\"params\":{\"prodKey\":\"%s\", \"deviceName\":\"%s\",\"encrypt\":\"payload\",\"randomKey\":\"%s\",\"sign\":\"%s\",\"accessKey\":\"%s\"}}"
|
||||
|
||||
int do_auth(CoAPContext *ctx, NetworkAddr *addr, ctl_key_item *ctl_item, void *user_data, AuthHandler handler)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
AlcsDeviceKey devKey;
|
||||
device_auth_list *dev = get_device(ctx);
|
||||
if (!dev) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, addr, sizeof(NetworkAddr));
|
||||
devKey.pk = ctl_item->productKey;
|
||||
devKey.dn = ctl_item->deviceName;
|
||||
|
||||
session_item *session = get_ctl_session(ctx, &devKey);
|
||||
if (session) {
|
||||
if (session->sessionId) {
|
||||
COAP_INFO("no need to reauth!");
|
||||
ResponseMsg res = {COAP_SUCCESS, NULL};
|
||||
handler(ctx, addr, user_data, &res);
|
||||
return COAP_SUCCESS;
|
||||
} else {
|
||||
COAP_INFO("is authing, no need to reauth!");
|
||||
return ALCS_ERR_AUTH_AUTHING;
|
||||
}
|
||||
}
|
||||
|
||||
/* create&save session item */
|
||||
{
|
||||
session = (session_item *)coap_malloc(sizeof(session_item));
|
||||
memset(session, 0, sizeof(session_item));
|
||||
|
||||
char path[100] = {0};
|
||||
strncpy(path, ctl_item->productKey, sizeof(path) - 1);
|
||||
strncat(path, ctl_item->deviceName, sizeof(path) - strlen(path) - 1);
|
||||
CoAPPathMD5_sum(path, strlen(path), session->pk_dn, PK_DN_CHECKSUM_LEN);
|
||||
COAP_INFO("pk:%s, dn:%s, checksum:%s", devKey.pk, devKey.dn, session->pk_dn);
|
||||
memcpy(&session->addr, addr, sizeof(NetworkAddr));
|
||||
gen_random_key((unsigned char *)session->randomKey, RANDOMKEY_LEN);
|
||||
|
||||
struct list_head *ctl_head = get_ctl_session_list(ctx);
|
||||
list_add_tail(&session->lst, ctl_head);
|
||||
}
|
||||
|
||||
char sign[64] = {0};
|
||||
int sign_len = sizeof(sign);
|
||||
utils_hmac_sha1_base64(session->randomKey, RANDOMKEY_LEN, ctl_item->accessToken,
|
||||
strlen(ctl_item->accessToken), sign, &sign_len);
|
||||
COAP_INFO("calc randomKey:%s,token:%s,sign:%.*s", session->randomKey, ctl_item->accessToken, sign_len, sign);
|
||||
|
||||
char payloadbuf[512];
|
||||
sprintf(payloadbuf, auth_payload_format, ++dev->seq, ctl_item->productKey, ctl_item->deviceName, session->randomKey,
|
||||
sign, ctl_item->accessKey);
|
||||
COAP_INFO("payload:%s", payloadbuf);
|
||||
|
||||
CoAPLenString payload;
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
CoAPMessage message;
|
||||
alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
|
||||
|
||||
char path[120];
|
||||
sprintf(path, "/dev/%s/%s/core/service/auth", ctl_item->productKey, ctl_item->deviceName);
|
||||
CoAPServerPath_2_option(path, &message);
|
||||
|
||||
AuthParam *authParam = (AuthParam *) coap_malloc(sizeof(AuthParam));
|
||||
authParam->handler = handler;
|
||||
authParam->user_data = user_data;
|
||||
authParam->productKey = (char *) coap_malloc(strlen(ctl_item->productKey) + 1);
|
||||
strcpy(authParam->productKey, ctl_item->productKey);
|
||||
authParam->deviceName = (char *) coap_malloc(strlen(ctl_item->deviceName) + 1);
|
||||
strcpy(authParam->deviceName, ctl_item->deviceName);
|
||||
authParam->accessToken = (char *) coap_malloc(strlen(ctl_item->accessToken) + 1);
|
||||
strcpy(authParam->accessToken, ctl_item->accessToken);
|
||||
message.user = authParam;
|
||||
message.handler = auth_cb;
|
||||
|
||||
ret = CoAPMessage_send(ctx, addr, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void alcs_auth_has_key(CoAPContext *ctx, NetworkAddr *addr, AuthParam *auth_param)
|
||||
{
|
||||
ctl_key_item item;
|
||||
item.accessKey = auth_param->accessKey;
|
||||
item.deviceName = auth_param->deviceName;
|
||||
item.productKey = auth_param->productKey;
|
||||
item.accessToken = auth_param->accessToken;/* (char*) coap_malloc (strlen(auth_param->accessToken) + 1); */
|
||||
/* strcpy (item.accessToken, auth_param->accessToken); */
|
||||
do_auth(ctx, addr, &item, auth_param->user_data, auth_param->handler);
|
||||
}
|
||||
|
||||
void alcs_auth_nego_key(CoAPContext *ctx, AlcsDeviceKey *devKey, AuthHandler handler)
|
||||
{
|
||||
COAP_DEBUG("alcs_auth_nego_key");
|
||||
|
||||
device_auth_list *dev = get_device(ctx);
|
||||
if (!dev) {
|
||||
COAP_INFO("no device!");
|
||||
return;
|
||||
}
|
||||
|
||||
char accesskeys[1024] = {0};
|
||||
if (!fillAccessKey(ctx, accesskeys)) {
|
||||
COAP_INFO("no ctl key!");
|
||||
return;
|
||||
}
|
||||
COAP_INFO("accesskeys:%s", accesskeys);
|
||||
|
||||
const char *method = "core/service/auth/select";
|
||||
char payloadbuf[1024];
|
||||
sprintf(payloadbuf, payload_format, method, ++dev->seq, devKey->pk, devKey->dn, accesskeys);
|
||||
|
||||
CoAPLenString payload;
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
CoAPMessage message;
|
||||
alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
|
||||
|
||||
char path[120];
|
||||
sprintf(path, "/dev/%s/%s/core/service/auth/select", devKey->pk, devKey->dn);
|
||||
CoAPServerPath_2_option(path, &message);
|
||||
|
||||
AuthParam *authParam = (AuthParam *) coap_malloc(sizeof(AuthParam));
|
||||
memset(authParam, 0, sizeof(AuthParam));
|
||||
|
||||
authParam->handler = handler;
|
||||
authParam->productKey = (char *) coap_malloc(strlen(devKey->pk) + 1);
|
||||
strcpy(authParam->productKey, devKey->pk);
|
||||
authParam->deviceName = (char *) coap_malloc(strlen(devKey->dn) + 1);
|
||||
strcpy(authParam->deviceName, devKey->dn);
|
||||
|
||||
message.user = authParam;
|
||||
message.handler = nego_cb;
|
||||
CoAPMessage_send(ctx, &devKey->addr, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
}
|
||||
|
||||
int alcs_add_client_key(CoAPContext *ctx, const char *accesskey, const char *accesstoken, const char *productKey,
|
||||
const char *deviceName)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
if (!lst || lst->ctl_count >= KEY_MAXCOUNT) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
ctl_key_item *item = (ctl_key_item *) coap_malloc(sizeof(ctl_key_item));
|
||||
if (!item) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
item->accessKey = (char *) coap_malloc(strlen(accesskey) + 1);
|
||||
item->accessToken = (char *) coap_malloc(strlen(accesstoken) + 1);
|
||||
|
||||
if (!item->accessKey || !item->accessToken) {
|
||||
coap_free(item);
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
strcpy(item->accessKey, accesskey);
|
||||
strcpy(item->accessToken, accesstoken);
|
||||
|
||||
if (deviceName) {
|
||||
item->deviceName = (char *) coap_malloc(strlen(deviceName) + 1);
|
||||
strcpy(item->deviceName, deviceName);
|
||||
}
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
list_add_tail(&item->lst, &lst->lst_ctl);
|
||||
++lst->ctl_count;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int alcs_remove_client_key(CoAPContext *ctx, const char *key, char isfullkey)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
if (!lst) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
ctl_key_item *node = NULL, *next = NULL;
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item) {
|
||||
if (match_key(node->accessKey, key)) {
|
||||
coap_free(node->accessKey);
|
||||
coap_free(node->accessToken);
|
||||
list_del(&node->lst);
|
||||
coap_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
bool alcs_device_online(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
session_item *session = get_ctl_session(ctx, devKey);
|
||||
return session && session->sessionId ? 1 : 0;
|
||||
}
|
||||
|
||||
void heart_beat_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
COAP_DEBUG("heart_beat_cb, message addr:%p, networkaddr:%p!", message, remote);
|
||||
|
||||
struct list_head *ctl_head = get_ctl_session_list(ctx);
|
||||
if (!ctl_head || list_empty(ctl_head)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == COAP_RECV_RESP_TIMEOUT) {
|
||||
COAP_ERR("heart beat timeout");
|
||||
session_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
|
||||
if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
|
||||
remove_session(ctx, node);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
session_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
|
||||
|
||||
if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
|
||||
unsigned int sessionId = 0;
|
||||
CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
|
||||
|
||||
if (node->sessionId != sessionId) {
|
||||
COAP_INFO("receive stale heart beat response");
|
||||
remove_session(ctx, node);
|
||||
} else {
|
||||
node->heart_time = HAL_UptimeMs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void on_client_auth_timer(CoAPContext *ctx)
|
||||
{
|
||||
struct list_head *ctl_head = get_ctl_session_list(ctx);
|
||||
if (!ctl_head || list_empty(ctl_head)) {
|
||||
return;
|
||||
}
|
||||
COAP_DEBUG("on_client_auth_timer:%d", (int)HAL_UptimeMs());
|
||||
|
||||
device_auth_list *dev = get_device(ctx);
|
||||
char payloadbuf[64];
|
||||
sprintf(payloadbuf, "{\"id\":%d,\"version\":\"1.0\",\"params\":{\"delayTime\":%d}}", ++dev->seq, 5000);
|
||||
|
||||
CoAPLenString payload;
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
int tick = HAL_UptimeMs();
|
||||
|
||||
session_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
|
||||
if (!node->sessionId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->heart_time + node->interval > tick) {
|
||||
CoAPMessage message;
|
||||
alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
|
||||
CoAPServerPath_2_option("/dev/core/service/heartBeat", &message);
|
||||
message.handler = heart_beat_cb;
|
||||
CoAPMessage_send(ctx, &node->addr, &message);
|
||||
COAP_DEBUG("send heartbeat to :%s", node->addr.addr);
|
||||
CoAPMessage_destory(&message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_coap.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPResource.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPServer.h"
|
||||
|
||||
#define MAX_PATH_CHECKSUM_LEN (5)
|
||||
typedef struct {
|
||||
char path[MAX_PATH_CHECKSUM_LEN];
|
||||
CoAPRecvMsgHandler cb;
|
||||
struct list_head lst;
|
||||
} resource_cb_item;
|
||||
|
||||
ALIYUN_LIST_HEAD(resource_cb_head);
|
||||
|
||||
static uint32_t tokenSeed = 0;
|
||||
uint32_t getToken()
|
||||
{
|
||||
if (tokenSeed == 0) {
|
||||
HAL_Srandom((uint32_t)HAL_UptimeMs());
|
||||
tokenSeed = HAL_Random(0xffffffff);
|
||||
} else {
|
||||
++tokenSeed;
|
||||
}
|
||||
|
||||
return tokenSeed;
|
||||
}
|
||||
|
||||
void alcs_msg_init(CoAPContext *ctx, CoAPMessage *message, int code, unsigned char type,
|
||||
int keep, CoAPLenString *payload, void *userdata)
|
||||
{
|
||||
uint32_t token = 0;
|
||||
|
||||
CoAPMessage_init(message);
|
||||
message->header.code = code;
|
||||
message->header.type = type;
|
||||
message->user = userdata;
|
||||
message->payload = payload->data;
|
||||
message->payloadlen = payload->len;
|
||||
message->keep = keep;
|
||||
|
||||
message->header.msgid = CoAPMessageId_gen(ctx);
|
||||
message->header.tokenlen = 4;
|
||||
token = getToken();
|
||||
memcpy(&message->token, &token, 4);
|
||||
}
|
||||
|
||||
void alcs_msg_deinit(CoAPMessage *message)
|
||||
{
|
||||
CoAPMessage_destory(message);
|
||||
}
|
||||
|
||||
static int do_sendmsg(CoAPContext *context, NetworkAddr *addr, CoAPMessage *message, char observe, unsigned short msgid,
|
||||
CoAPLenString *token)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
if (!context || !addr || !message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (msgid == 0) {
|
||||
message->header.msgid = CoAPMessageId_gen(context);
|
||||
} else {
|
||||
message->header.msgid = msgid;
|
||||
}
|
||||
|
||||
if (observe == 0) {
|
||||
CoAPUintOption_add(message, COAP_OPTION_OBSERVE, observe);
|
||||
}
|
||||
|
||||
if (token) {
|
||||
message->header.tokenlen = token->len;
|
||||
memcpy(&message->token, token->data, token->len);
|
||||
}
|
||||
|
||||
ret = CoAPMessage_send(context, addr, message);
|
||||
CoAPMessage_destory(message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int alcs_sendmsg(CoAPContext *context, NetworkAddr *addr, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler)
|
||||
{
|
||||
message->handler = handler;
|
||||
return do_sendmsg(context, addr, message, observe, message->header.msgid, NULL);
|
||||
}
|
||||
|
||||
int alcs_sendrsp(CoAPContext *context, NetworkAddr *addr, CoAPMessage *message, char observe, unsigned short msgid,
|
||||
CoAPLenString *token)
|
||||
{
|
||||
return do_sendmsg(context, addr, message, observe, msgid, token);
|
||||
}
|
||||
|
||||
/* observe */
|
||||
int alcs_observe_notify(CoAPContext *context, const char *path, CoAPLenString *payload)
|
||||
{
|
||||
int needAuth = 0;
|
||||
#ifdef USE_ALCS_SECURE
|
||||
needAuth = alcs_resource_need_auth(context, path);
|
||||
#endif
|
||||
COAP_DEBUG("payload:%s", payload->data);
|
||||
/* HEXDUMP_DEBUG(payload->data, payload->len); */
|
||||
return CoAPObsServer_notify(context, path, payload->data, payload->len,
|
||||
needAuth ? &observe_data_encrypt : NULL);
|
||||
}
|
||||
|
||||
static void send_err_rsp(CoAPContext *ctx, NetworkAddr *addr, int code, CoAPMessage *fromMsg)
|
||||
{
|
||||
CoAPMessage sendMsg;
|
||||
CoAPLenString payload = {0};
|
||||
CoAPLenString token = {fromMsg->header.tokenlen, fromMsg->token};
|
||||
|
||||
alcs_msg_init(ctx, &sendMsg, code, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
|
||||
alcs_sendrsp(ctx, addr, &sendMsg, 1, fromMsg->header.msgid, &token);
|
||||
}
|
||||
|
||||
static void recv_msg_handler(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
unsigned int obsVal;
|
||||
resource_cb_item *node = NULL, *next = NULL;
|
||||
char path_calc[MAX_PATH_CHECKSUM_LEN] = {0};
|
||||
CoAPPathMD5_sum(path, strlen(path), path_calc, MAX_PATH_CHECKSUM_LEN);
|
||||
|
||||
list_for_each_entry_safe(node, next, &resource_cb_head, lst, resource_cb_item) {
|
||||
if (0 == memcmp(path_calc, node->path, MAX_PATH_CHECKSUM_LEN)) {
|
||||
if (CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &obsVal) == COAP_SUCCESS) {
|
||||
if (obsVal == 0) {
|
||||
CoAPObsServer_add(context, path, remote, message);
|
||||
}
|
||||
}
|
||||
COAP_INFO("recv_msg_handler call callback");
|
||||
node->cb(context, path, remote, message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
COAP_ERR("receive unknown request, path:%s", path);
|
||||
send_err_rsp(context, remote, COAP_MSG_CODE_401_UNAUTHORIZED, message);
|
||||
}
|
||||
|
||||
/* resource */
|
||||
int alcs_resource_register(CoAPContext *context, const char *pk, const char *dn, const char *path,
|
||||
unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage, char needAuth, CoAPRecvMsgHandler callback)
|
||||
{
|
||||
COAP_DEBUG("alcs_resource_register, ctx:%p", context);
|
||||
COAP_DEBUG("ALCS Resource Register: %s", path);
|
||||
|
||||
if (!needAuth) {
|
||||
resource_cb_item *item = (resource_cb_item *)coap_malloc(sizeof(resource_cb_item));
|
||||
CoAPPathMD5_sum(path, strlen(path), item->path, MAX_PATH_CHECKSUM_LEN);
|
||||
item->cb = callback;
|
||||
list_add_tail(&item->lst, &resource_cb_head);
|
||||
|
||||
return CoAPResource_register(context, path, permission, ctype, maxage, &recv_msg_handler);
|
||||
} else {
|
||||
#ifdef USE_ALCS_SECURE
|
||||
return alcs_resource_register_secure(context, pk, dn, path, permission, ctype, maxage, callback);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int alcs_resource_need_auth(CoAPContext *context, const char *path)
|
||||
{
|
||||
resource_cb_item *node = NULL, *next = NULL;
|
||||
char path_calc[MAX_PATH_CHECKSUM_LEN] = {0};
|
||||
CoAPPathMD5_sum(path, strlen(path), path_calc, MAX_PATH_CHECKSUM_LEN);
|
||||
|
||||
list_for_each_entry_safe(node, next, &resource_cb_head, lst, resource_cb_item) {
|
||||
if (memcmp(path_calc, node->path, MAX_PATH_CHECKSUM_LEN) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
CoAPContext *ctx;
|
||||
char loop;
|
||||
bool inited;
|
||||
struct list_head lst;
|
||||
} ALCSContext;
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
ALIYUN_LIST_HEAD(context_head);
|
||||
|
||||
ALCSContext *get_context(CoAPContext *ctx)
|
||||
{
|
||||
ALCSContext *node = NULL, *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &context_head, lst, ALCSContext) {
|
||||
if (node->ctx == ctx) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CoAPContext *alcs_context_create(CoAPInitParam *param)
|
||||
{
|
||||
ALCSContext *alcs_ctx = (ALCSContext *) coap_malloc(sizeof(ALCSContext));
|
||||
alcs_ctx->ctx = CoAPContext_create(param);
|
||||
COAP_INFO("CoAPContext_create return :%p", alcs_ctx->ctx);
|
||||
alcs_ctx->loop = 0;
|
||||
alcs_ctx->inited = 0;
|
||||
|
||||
list_add_tail(&alcs_ctx->lst, &context_head);
|
||||
return alcs_ctx->ctx;
|
||||
}
|
||||
|
||||
void alcs_context_free(CoAPContext *ctx)
|
||||
{
|
||||
ALCSContext *alcs_ctx = get_context(ctx);
|
||||
if (alcs_ctx) {
|
||||
CoAPContext_free(alcs_ctx->ctx);
|
||||
coap_free(alcs_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
ALCSContext *g_alcs_ctx = NULL;
|
||||
ALCSContext *get_context(CoAPContext *ctx)
|
||||
{
|
||||
return g_alcs_ctx;
|
||||
}
|
||||
|
||||
CoAPContext *alcs_context_init(CoAPInitParam *param)
|
||||
{
|
||||
if (g_alcs_ctx) {
|
||||
return g_alcs_ctx->ctx;
|
||||
}
|
||||
|
||||
g_alcs_ctx = (ALCSContext *)coap_malloc(sizeof(ALCSContext));
|
||||
if (g_alcs_ctx) {
|
||||
g_alcs_ctx->loop = 0;
|
||||
g_alcs_ctx->inited = 0;
|
||||
g_alcs_ctx->ctx = CoAPServer_init();
|
||||
COAP_INFO("CoAPServer_init return :%p", g_alcs_ctx->ctx);
|
||||
if (!g_alcs_ctx->ctx) {
|
||||
coap_free(g_alcs_ctx);
|
||||
g_alcs_ctx = NULL;
|
||||
return NULL;
|
||||
}
|
||||
return g_alcs_ctx->ctx;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void alcs_context_deinit()
|
||||
{
|
||||
if (g_alcs_ctx) {
|
||||
if (g_alcs_ctx->ctx) {
|
||||
CoAPServer_deinit(g_alcs_ctx->ctx);
|
||||
}
|
||||
coap_free(g_alcs_ctx);
|
||||
g_alcs_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CoAPContext *alcs_get_context()
|
||||
{
|
||||
return g_alcs_ctx ? g_alcs_ctx->ctx : NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern void on_auth_timer(void *arg);
|
||||
|
||||
void *thread_routine(void *arg)
|
||||
{
|
||||
ALCSContext *ctx = (ALCSContext *)arg;
|
||||
ctx->loop = 1;
|
||||
|
||||
COAP_INFO("thread_routine");
|
||||
|
||||
while (ctx->loop) {
|
||||
CoAPMessage_cycle(ctx->ctx);
|
||||
#ifdef USE_ALCS_SECURE
|
||||
on_auth_timer(ctx->ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void alcs_start_loop(CoAPContext *ctx, int newThread)
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
void *handle = NULL;
|
||||
ALCSContext *alcs_ctx = get_context(ctx);
|
||||
if (alcs_ctx && !alcs_ctx->loop) {
|
||||
int stack_used = 0;
|
||||
if (!newThread || 0 != HAL_ThreadCreate(&handle, thread_routine, alcs_ctx, NULL, &stack_used)) {
|
||||
thread_routine(alcs_ctx);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#ifdef USE_ALCS_SECURE
|
||||
CoAPServer_add_timer(on_auth_timer);
|
||||
#endif
|
||||
CoAPServer_loop(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void alcs_stop_loop(CoAPContext *ctx)
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
ALCSContext *alcs_ctx = get_context(ctx);
|
||||
if (alcs_ctx) {
|
||||
alcs_ctx->loop = 0;
|
||||
}
|
||||
#else
|
||||
CoAPServer_deinit(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void alcs_init()
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
INIT_LIST_HEAD(&context_head);
|
||||
#endif
|
||||
INIT_LIST_HEAD(&resource_cb_head);
|
||||
}
|
||||
|
||||
void alcs_deinit()
|
||||
{
|
||||
resource_cb_item *del_item = NULL;
|
||||
|
||||
list_for_each_entry(del_item, &resource_cb_head, lst, resource_cb_item) {
|
||||
list_del(&del_item->lst);
|
||||
coap_free(del_item);
|
||||
del_item = list_entry(&resource_cb_head, resource_cb_item, lst);
|
||||
}
|
||||
}
|
||||
|
||||
static int path_2_option(const char *uri, CoAPMessage *message)
|
||||
{
|
||||
const char *ptr = NULL;
|
||||
const char *pstr = NULL;
|
||||
char path[COAP_MSG_MAX_PATH_LEN] = {0};
|
||||
|
||||
if (256 < strlen(uri)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
COAP_DEBUG("The uri is %s", uri);
|
||||
ptr = pstr = uri;
|
||||
while ('\0' != *ptr) {
|
||||
if ('/' == *ptr) {
|
||||
if (ptr != pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, ptr - pstr);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)(ptr - pstr));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
pstr = ptr + 1;
|
||||
|
||||
}
|
||||
if ('\0' == *(ptr + 1) && '\0' != *pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, sizeof(path) - 1);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)strlen(path));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
ptr ++;
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int alcs_msg_setAddr(CoAPMessage *message, const char *path, const char *query)
|
||||
{
|
||||
int rt = 0;
|
||||
|
||||
if (NULL == path || NULL == message) {
|
||||
COAP_ERR("Invalid paramter p_path %p, p_message %p", path, message);
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (255 < strlen(path)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(path));
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
rt = path_2_option(path, message);
|
||||
if (query) {
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_QUERY, (unsigned char *)query, strlen(query));
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "CoAPExport.h"
|
||||
|
||||
#ifndef __COAP_ALCS_H__
|
||||
#define __COAP_ALCS_H__
|
||||
|
||||
#define OPTSESESSION 62
|
||||
#define ALCSPORT 5683
|
||||
#define ALCSPORT_SECURE 5684
|
||||
#define MULTICAST_ADDRESS "224.0.1.187"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef bool
|
||||
#define bool char
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
NetworkAddr addr;
|
||||
char *path;
|
||||
char *query;
|
||||
} ResourceAddr;
|
||||
|
||||
/* 会自动生成msgid & token */
|
||||
void alcs_msg_init(CoAPContext *ctx, CoAPMessage *message, int code, unsigned char type, int keep,
|
||||
CoAPLenString *payload, void *userdata);
|
||||
void alcs_msg_deinit(CoAPMessage *message);
|
||||
int alcs_msg_setAddr(CoAPMessage *message, const char *path, const char *query);
|
||||
|
||||
/* observe: 0 register */
|
||||
/* observer:1 deregister */
|
||||
/* observer:other 没意义 */
|
||||
int alcs_sendmsg(CoAPContext *ctx, NetworkAddr *addr, CoAPMessage *message, char observe, CoAPSendMsgHandler handler);
|
||||
|
||||
/* msgid & token从接收到CoAPMessage获取, 若发送的是事件通知,msgid设置为0 */
|
||||
/* observe: 0: accept register */
|
||||
/* observe: other: 没意义 */
|
||||
int alcs_sendrsp(CoAPContext *ctx, NetworkAddr *addr, CoAPMessage *message, char observe, unsigned short msgid,
|
||||
CoAPLenString *token);
|
||||
|
||||
void alcs_start_loop(CoAPContext *ctx, int newThread);
|
||||
void alcs_stop_loop(CoAPContext *ctx);
|
||||
|
||||
/* 服务端接口
|
||||
*
|
||||
*/
|
||||
/* observe */
|
||||
int alcs_observe_notify(CoAPContext *context, const char *path, CoAPLenString *payload);
|
||||
|
||||
/* resource */
|
||||
int alcs_resource_register(CoAPContext *context, const char *pk, const char *dn, const char *path,
|
||||
unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage, char needAuth, CoAPRecvMsgHandler callback);
|
||||
|
||||
int alcs_resource_need_auth(CoAPContext *context, const char *path);
|
||||
|
||||
|
||||
/* init */
|
||||
void alcs_init();
|
||||
void alcs_deinit();
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
CoAPContext *alcs_context_create(CoAPInitParam *param);
|
||||
void alcs_context_free(CoAPContext *ctx);
|
||||
#else
|
||||
CoAPContext *alcs_context_init(CoAPInitParam *param);
|
||||
void alcs_context_deinit();
|
||||
CoAPContext *alcs_get_context();
|
||||
#endif
|
||||
|
||||
/* option */
|
||||
extern int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum, unsigned int data);
|
||||
extern int CoAPUintOption_get(CoAPMessage *message, unsigned short optnum, unsigned int *data);
|
||||
extern int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short datalen);
|
||||
extern int CoAPMessage_cancel(CoAPContext *context, CoAPMessage *message);
|
||||
|
||||
uint32_t getToken();
|
||||
|
||||
/* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _ALCS_INTERNAL_H_
|
||||
#define _ALCS_INTERNAL_H_
|
||||
|
||||
#include "infra_config.h"
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_md5.h"
|
||||
#include "infra_sha1.h"
|
||||
#include "infra_json_parser.h"
|
||||
#include "alcs_base64.h"
|
||||
#include "dm_wrapper.h"
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define ALCS_malloc(size) LITE_malloc(size, MEM_MAGIC, "alcs")
|
||||
#define ALCS_ADAPTER_malloc(size) LITE_malloc(size, MEM_MAGIC, "alcs_adapter")
|
||||
#define ALCS_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define ALCS_malloc(size) HAL_Malloc(size)
|
||||
#define ALCS_ADAPTER_malloc(size) HAL_Malloc(size)
|
||||
#define ALCS_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "iotx_alcs.h"
|
||||
|
||||
char *DEFAULT_AC = "Xtau@iot";
|
||||
char *DEFAULT_AS = "Yx3DdsyetbSezlvc";
|
||||
void *g_adapter_handle = NULL;
|
||||
void *g_coap_handle = NULL;
|
||||
|
||||
typedef enum {
|
||||
ALCS_LOCALSETUP_SUCCESS,
|
||||
ALCS_LOCALSETUP_ERROR
|
||||
} localsetup_status;
|
||||
|
||||
static localsetup_status __alcs_localsetup_kv_set(const char *key, const void *val, int len, int sync)
|
||||
{
|
||||
if (HAL_Kv_Set(key, val, len, sync) != 0) {
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Set, Key: %s, Val: %s, Len: %d", key, (char *)val, len);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_kv_get(const char *key, void *buffer, int *buffer_len)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
if ((rc = HAL_Kv_Get(key, buffer, buffer_len)) != 0) {
|
||||
COAP_WRN("HAL_Kv_Get('%s') = %d (!= 0), return %d", key, rc, ALCS_LOCALSETUP_ERROR);
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Get, Key: %s", key);
|
||||
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_kv_del(const char *key)
|
||||
{
|
||||
if (HAL_Kv_Del(key) != 0) {
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Del, Key: %s", key);
|
||||
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __fill_key(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len, char key_md5_hexstr[33])
|
||||
{
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_source[IOTX_PRODUCT_KEY_LEN + 1 + IOTX_DEVICE_NAME_LEN + 1 + 3];
|
||||
|
||||
if (pk == NULL || pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
HAL_Snprintf(key_source, sizeof(key_source), "%.*s%.*s.l", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_ac_as_save(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
const char *prefix, uint16_t prefix_len,
|
||||
const char *secret, uint16_t secret_len)
|
||||
{
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char *value = NULL;
|
||||
int rt;
|
||||
if (prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
|
||||
if (rt != ALCS_LOCALSETUP_SUCCESS) {
|
||||
return rt;
|
||||
}
|
||||
|
||||
/* Calculate Value */
|
||||
value = ALCS_ADAPTER_malloc(prefix_len + secret_len + 3);
|
||||
if (value == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
memset(value, 0, prefix_len + secret_len + 3);
|
||||
|
||||
value[0] = prefix_len;
|
||||
value[1] = secret_len;
|
||||
HAL_Snprintf(&value[2], prefix_len + secret_len + 1, "%.*s%.*s", prefix_len, prefix, secret_len, secret);
|
||||
|
||||
if (ALCS_LOCALSETUP_SUCCESS != __alcs_localsetup_kv_set(key_md5_hexstr, value, prefix_len + secret_len + 3, 1)) {
|
||||
COAP_WRN("ALCS KV Set Prefix And Secret Fail");
|
||||
ALCS_free(value);
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
ALCS_free(value);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
localsetup_status alcs_localsetup_ac_as_load(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
char *prefix, int prefix_len, char *secret, int secret_len)
|
||||
{
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char value[128] = {0};
|
||||
int value_len = sizeof(value);
|
||||
|
||||
int rt;
|
||||
if (prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
|
||||
if (rt != ALCS_LOCALSETUP_SUCCESS) {
|
||||
return rt;
|
||||
}
|
||||
|
||||
/* Get Value */
|
||||
if (ALCS_LOCALSETUP_SUCCESS != __alcs_localsetup_kv_get(key_md5_hexstr, value, &value_len)) {
|
||||
COAP_WRN("ALCS KV Get local Prefix And Secret Fail");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
if (value[0] >= prefix_len || value[1] >= secret_len) {
|
||||
COAP_ERR("insuffient buffer!");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
memset(prefix, 0, prefix_len);
|
||||
memcpy(prefix, &value[2], value[0]);
|
||||
memset(secret, 0, secret_len);
|
||||
memcpy(secret, &value[2 + value[0]], value[1]);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_ac_as_del(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len)
|
||||
{
|
||||
char key_md5_hexstr[33] = {0};
|
||||
int rt;
|
||||
rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
|
||||
if (rt != ALCS_LOCALSETUP_SUCCESS) {
|
||||
return rt;
|
||||
}
|
||||
|
||||
if (ALCS_LOCALSETUP_SUCCESS != __alcs_localsetup_kv_del(key_md5_hexstr)) {
|
||||
COAP_ERR("ALCS KV Get local Prefix And Secret Fail");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static void alcs_service_cb_setup(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
char payload[128];
|
||||
char *id = NULL, *p;
|
||||
int idlen = 0, len, aclen, aslen, pklen, dnlen;
|
||||
char *ac = NULL, *as = NULL, *pk = NULL, *dn = dn;
|
||||
bool success = 0;
|
||||
char *err_msg = NULL;
|
||||
char configValueBack, acBack, asBack;
|
||||
char *str_pos, *entry;
|
||||
int entry_len, type;
|
||||
iotx_alcs_msg_t rsp_msg;
|
||||
|
||||
COAP_DEBUG("alcs_service_cb_setup, path:%s", paths);
|
||||
do {
|
||||
if (!remote || !message) {
|
||||
COAP_DEBUG("alcs_service_cb_setup, param is NULL!");
|
||||
err_msg = "invalid package";
|
||||
break;
|
||||
}
|
||||
|
||||
id = json_get_value_by_name((char *)message->payload, message->payloadlen, "id", &idlen, (int *)NULL);
|
||||
p = json_get_value_by_name((char *)message->payload, message->payloadlen, "params", &len, (int *)NULL);
|
||||
if (!p || !len) {
|
||||
err_msg = "params is not found";
|
||||
break;
|
||||
}
|
||||
|
||||
p = json_get_value_by_name(p, len, "configValue", &len, (int *)NULL);
|
||||
if (!p || !len) {
|
||||
err_msg = "configValue is not found";
|
||||
break;
|
||||
}
|
||||
|
||||
backup_json_str_last_char(p, len, configValueBack);
|
||||
|
||||
json_array_for_each_entry(p, len, str_pos, entry, entry_len, type) {
|
||||
COAP_DEBUG("entry:%.*s", entry_len, entry);
|
||||
ac = json_get_value_by_name(entry, entry_len, "authCode", &aclen, (int *)NULL);
|
||||
as = json_get_value_by_name(entry, entry_len, "authSecret", &aslen, (int *)NULL);
|
||||
pk = json_get_value_by_name(entry, entry_len, "productKey", &pklen, (int *)NULL);
|
||||
dn = json_get_value_by_name(entry, entry_len, "deviceName", &dnlen, (int *)NULL);
|
||||
break;
|
||||
} /* end json_array_for_each_entry */
|
||||
restore_json_str_last_char(p, len, configValueBack);
|
||||
|
||||
if (!ac || !aclen || !as || !aslen || !pk || !pklen || !dn || !dnlen) {
|
||||
err_msg = "authinfo is not found";
|
||||
break;
|
||||
}
|
||||
|
||||
/* save */
|
||||
backup_json_str_last_char(ac, aclen, acBack);
|
||||
backup_json_str_last_char(as, aslen, asBack);
|
||||
__alcs_localsetup_ac_as_del(pk, pklen, dn, dnlen);
|
||||
__alcs_localsetup_ac_as_save(pk, pklen, dn, dnlen, ac, aclen, as, aslen);
|
||||
|
||||
alcs_add_svr_key(g_coap_handle, ac, as, LOCALSETUP);
|
||||
|
||||
restore_json_str_last_char(ac, aclen, acBack);
|
||||
restore_json_str_last_char(as, aslen, asBack)
|
||||
success = 1;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (success) {
|
||||
HAL_Snprintf(payload, sizeof(payload), "{\"id\":\"%.*s\",\"code\":200}", idlen, id ? id : "");
|
||||
} else {
|
||||
HAL_Snprintf(payload, sizeof(payload), "{\"id\":\"%.*s\",\"code\":400,\"msg\":\"%s\"}", idlen, id ? id : "", err_msg);
|
||||
COAP_ERR("alcs_service_cb_setup, %s", err_msg);
|
||||
}
|
||||
|
||||
memset(&rsp_msg, 0, sizeof(iotx_alcs_msg_t));
|
||||
|
||||
rsp_msg.msg_code = ITOX_ALCS_COAP_MSG_CODE_205_CONTENT;
|
||||
rsp_msg.msg_type = IOTX_ALCS_MESSAGE_TYPE_CON;
|
||||
rsp_msg.payload = (unsigned char *)payload;
|
||||
rsp_msg.payload_len = strlen(payload);
|
||||
rsp_msg.ip = (char *)(remote ? remote->addr : NULL);
|
||||
rsp_msg.port = remote ? remote->port : 5683;
|
||||
rsp_msg.uri = (char *)paths;
|
||||
|
||||
if (message) {
|
||||
iotx_alcs_send_Response(g_adapter_handle, &rsp_msg, message->header.tokenlen, message->token);
|
||||
}
|
||||
}
|
||||
|
||||
static void alcs_localsetup_register_resource(void *adapter_handle, char *pk, char *dn)
|
||||
{
|
||||
iotx_alcs_res_t alcs_res;
|
||||
char uri [IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 24];
|
||||
|
||||
if (adapter_handle == NULL || pk == NULL || strlen(pk) > IOTX_PRODUCT_KEY_LEN ||
|
||||
dn == NULL || strlen(dn) > IOTX_DEVICE_NAME_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_Snprintf(uri, sizeof(uri), "/dev/%s/%s/core/service/setup", pk, dn);
|
||||
|
||||
memset(&alcs_res, 0, sizeof(iotx_alcs_res_t));
|
||||
alcs_res.uri = uri;
|
||||
alcs_res.msg_ct = IOTX_ALCS_MESSAGE_CT_APP_JSON;
|
||||
alcs_res.msg_perm = IOTX_ALCS_MESSAGE_PERM_GET | IOTX_ALCS_MESSAGE_PERM_PUT;
|
||||
alcs_res.maxage = 60;
|
||||
alcs_res.need_auth = 1;
|
||||
alcs_res.callback = alcs_service_cb_setup;
|
||||
|
||||
iotx_alcs_register_resource(adapter_handle, &alcs_res);
|
||||
}
|
||||
|
||||
void alcs_localsetup_init(void *adapter_handle, void *coap_handler, char *pk, char *dn)
|
||||
{
|
||||
char prefix [10];
|
||||
char secret [64];
|
||||
g_adapter_handle = adapter_handle;
|
||||
g_coap_handle = coap_handler;
|
||||
alcs_localsetup_register_resource(adapter_handle, pk, dn);
|
||||
|
||||
if (alcs_localsetup_ac_as_load(pk, strlen(pk), dn, strlen(dn), prefix, sizeof(prefix), secret,
|
||||
sizeof(secret)) != ALCS_LOCALSETUP_SUCCESS) {
|
||||
alcs_add_svr_key(g_coap_handle, DEFAULT_AC, DEFAULT_AS, LOCALDEFAULT);
|
||||
} else {
|
||||
alcs_add_svr_key(g_coap_handle, prefix, secret, LOCALSETUP);
|
||||
}
|
||||
}
|
||||
|
||||
void alcs_localsetup_add_sub_device(void *adapter_handle, char *pk, char *dn)
|
||||
{
|
||||
alcs_localsetup_register_resource(adapter_handle, pk, dn);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _ALCS_LOCALSETUP_H_
|
||||
#define _ALCS_LOCALSETUP_H_
|
||||
|
||||
void alcs_localsetup_init(void *adapter_handle, void* coap_handler, char *product_key,char *device_name);
|
||||
void alcs_localsetup_add_sub_device (void *adapter_handle,char *product_key,char *device_name);
|
||||
void alcs_localsetup_deinit(void *handle);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,618 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "CoAPPlatform.h"
|
||||
|
||||
static alcs_mqtt_ctx_t g_alcs_mqtt_ctx;
|
||||
|
||||
static alcs_mqtt_ctx_t *__alcs_mqtt_get_ctx(void)
|
||||
{
|
||||
return &g_alcs_mqtt_ctx;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_publish(char *topic, int qos, void *data, int len)
|
||||
{
|
||||
return (IOT_MQTT_Publish_Simple(NULL, topic, qos, data, len) < 0) ? ALCS_MQTT_STATUS_ERROR : ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_send_response(char *topic, int id, int code, char *data)
|
||||
{
|
||||
char *msg_pub = NULL;
|
||||
uint16_t msg_len = 0;
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
|
||||
if (data == NULL || strlen(data) == 0) {
|
||||
data = "{}";
|
||||
}
|
||||
|
||||
msg_len = strlen(ALCS_MQTT_THING_LAN_PREFIX_RESPONSE_FMT) + 20 + strlen(data) + 1;
|
||||
|
||||
if ((msg_pub = ALCS_ADAPTER_malloc(msg_len)) == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
HAL_Snprintf(msg_pub, msg_len, ALCS_MQTT_THING_LAN_PREFIX_RESPONSE_FMT, id, code, data);
|
||||
|
||||
status = __alcs_mqtt_publish(topic, 1, msg_pub, strlen(msg_pub));
|
||||
|
||||
ALCS_free(msg_pub);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_kv_set(const char *key, const void *val, int len, int sync)
|
||||
{
|
||||
if (HAL_Kv_Set(key, val, len, sync) != 0) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Set, Key: %s, Val: %s, Len: %d", key, (char *)val, len);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_kv_get(const char *key, void *buffer, int *buffer_len)
|
||||
{
|
||||
if (HAL_Kv_Get(key, buffer, buffer_len) != 0) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Get, Key: %s", key);
|
||||
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_kv_del(const char *key)
|
||||
{
|
||||
if (HAL_Kv_Del(key) != 0) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Del, Key: %s", key);
|
||||
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e __alcs_mqtt_prefix_secret_save(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
const char *prefix, uint16_t prefix_len,
|
||||
const char *secret, uint16_t secret_len)
|
||||
{
|
||||
char *key_source = NULL;
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char *value = NULL;
|
||||
|
||||
if (pk == NULL || pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || dn_len >= IOTX_DEVICE_NAME_LEN + 1 ||
|
||||
prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
key_source = ALCS_ADAPTER_malloc(pk_len + dn_len + 1);
|
||||
if (key_source == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(key_source, 0, pk_len + dn_len + 1);
|
||||
|
||||
HAL_Snprintf(key_source, pk_len + dn_len + 1, "%.*s%.*s", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
|
||||
/* Calculate Value */
|
||||
value = ALCS_ADAPTER_malloc(prefix_len + secret_len + 3);
|
||||
if (value == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(value, 0, prefix_len + secret_len + 3);
|
||||
|
||||
value[0] = prefix_len;
|
||||
value[1] = secret_len;
|
||||
HAL_Snprintf(&value[2], prefix_len + secret_len + 1, "%.*s%.*s", prefix_len, prefix, secret_len, secret);
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(key_md5_hexstr, value, prefix_len + secret_len + 3, 1)) {
|
||||
COAP_ERR("ALCS KV Set Prefix And Secret Fail");
|
||||
ALCS_free(key_source);
|
||||
ALCS_free(value);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
ALCS_free(key_source);
|
||||
ALCS_free(value);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_prefix_secret_load(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
char *prefix, char *secret)
|
||||
{
|
||||
char *key_source = NULL;
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char value[128] = {0};
|
||||
int value_len = sizeof(value);
|
||||
|
||||
if (pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1 ||
|
||||
prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
key_source = ALCS_ADAPTER_malloc(pk_len + dn_len + 1);
|
||||
if (key_source == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(key_source, 0, pk_len + dn_len + 1);
|
||||
|
||||
HAL_Snprintf(key_source, pk_len + dn_len + 1, "%.*s%.*s", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
|
||||
/* Get Value */
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_get(key_md5_hexstr, value, &value_len)) {
|
||||
COAP_ERR("ALCS KV Get Prefix And Secret Fail");
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memcpy(prefix, &value[2], value[0]);
|
||||
memcpy(secret, &value[2 + value[0]], value[1]);
|
||||
ALCS_free(key_source);
|
||||
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_prefix_secret_del(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len)
|
||||
{
|
||||
char *key_source = NULL;
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_md5_hexstr[33] = {0};
|
||||
|
||||
if (pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
key_source = ALCS_ADAPTER_malloc(pk_len + dn_len + 1);
|
||||
if (key_source == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(key_source, 0, pk_len + dn_len + 1);
|
||||
|
||||
HAL_Snprintf(key_source, pk_len + dn_len + 1, "%.*s%.*s", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_del(key_md5_hexstr)) {
|
||||
COAP_ERR("ALCS KV Get Prefix And Secret Fail");
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void __alcs_mqtt_subscribe_callback(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
|
||||
{
|
||||
char topic_compare[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
char reqid[16] = {0};
|
||||
char *topic;
|
||||
int topic_len;
|
||||
void *payload;
|
||||
int payload_len;
|
||||
alcs_mqtt_ctx_t *alcs_mqtt_ctx = NULL;
|
||||
iotx_mqtt_topic_info_pt ptopic_info = NULL;
|
||||
|
||||
if (msg == NULL) {
|
||||
return;
|
||||
}
|
||||
alcs_mqtt_ctx = (alcs_mqtt_ctx_t *)pcontext;
|
||||
ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;
|
||||
|
||||
switch (msg->event_type) {
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS:
|
||||
return;
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT:
|
||||
return;
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_NACK:
|
||||
return;
|
||||
case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
|
||||
topic = (char *)ptopic_info->ptopic;
|
||||
topic_len = ptopic_info->topic_len;
|
||||
payload = (char *)ptopic_info->payload;
|
||||
payload_len = ptopic_info->payload_len;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (topic == NULL || payload == NULL || topic_len == 0 || payload_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(topic_compare, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic_compare, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
|
||||
COAP_INFO("Receivce Message, Topic: %.*s\n", topic_len, topic);
|
||||
|
||||
if ((strlen(topic_compare) == topic_len) && (strncmp(topic_compare, topic, topic_len) == 0)) {
|
||||
int data_len = 0, prefix_len = 0, secret_len = 0, productKey_len = 0, deviceName_len = 0;
|
||||
char *data = NULL, *prefix = NULL, *secret = NULL, *productKey = NULL, *deviceName = NULL;
|
||||
data = json_get_value_by_name((char *)payload, payload_len, "data", &data_len, NULL);
|
||||
|
||||
if (NULL != data && 0 != data_len) {
|
||||
char back1, back2;
|
||||
prefix = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_PREFIX, &prefix_len, NULL);
|
||||
secret = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_SECRET, &secret_len, NULL);
|
||||
productKey = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_PRODUCT_KEY, &productKey_len, NULL);
|
||||
deviceName = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_DEVICE_NAME, &deviceName_len, NULL);
|
||||
|
||||
COAP_INFO("Get Reply, Product Key: %.*s, Device Name: %.*s\n", productKey_len, productKey, deviceName_len, deviceName);
|
||||
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && prefix && secret) {
|
||||
back1 = prefix[prefix_len];
|
||||
prefix[prefix_len] = 0;
|
||||
back2 = secret[secret_len];
|
||||
secret[secret_len] = 0;
|
||||
alcs_add_svr_key(alcs_mqtt_ctx->coap_ctx, prefix, secret, FROMCLOUDSVR);
|
||||
prefix[prefix_len] = back1;
|
||||
secret[secret_len] = back2;
|
||||
|
||||
if (productKey && deviceName) {
|
||||
if (__alcs_mqtt_prefix_secret_save(productKey, productKey_len, deviceName, deviceName_len, prefix, prefix_len, secret,
|
||||
secret_len) == ALCS_MQTT_STATUS_SUCCESS) {
|
||||
iotx_alcs_subdev_item_t subdev_item;
|
||||
memset(&subdev_item, 0, sizeof(iotx_alcs_subdev_item_t));
|
||||
|
||||
memcpy(subdev_item.product_key, productKey, productKey_len);
|
||||
memcpy(subdev_item.device_name, deviceName, deviceName_len);
|
||||
subdev_item.stage = IOTX_ALCS_SUBDEV_CONNECT_CLOUD;
|
||||
|
||||
iotx_alcs_subdev_update_stage(&subdev_item);
|
||||
}
|
||||
} else {
|
||||
iotx_alcs_subdev_remove(alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(ALCS_MQTT_JSON_KEY_PREFIX, prefix, prefix_len, 1)) {
|
||||
COAP_ERR("ALCS KV Set Prefix Fail");
|
||||
}
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(ALCS_MQTT_JSON_KEY_SECRET, secret, secret_len, 1)) {
|
||||
COAP_ERR("ALCS KV Set Secret Fail");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_PREFIX, prefix, &prefix_len) &&
|
||||
ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_SECRET, secret, &secret_len)) {
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && prefix_len && secret_len) {
|
||||
alcs_add_svr_key(alcs_mqtt_ctx->coap_ctx, prefix, secret, FROMCLOUDSVR);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
memset(topic_compare, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic_compare, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
|
||||
if ((strlen(topic_compare) == topic_len) && (strncmp(topic_compare, topic, topic_len) == 0)) {
|
||||
int param_len = 0, prefix_len = 0, id_len = 0;
|
||||
char *param = NULL, *prefix = NULL, *id = NULL;
|
||||
id = json_get_value_by_name((char *)payload, payload_len, "id", &id_len, NULL);
|
||||
|
||||
if (NULL != id && 0 != id_len) {
|
||||
strncpy(reqid, id, sizeof(reqid) - 1);
|
||||
}
|
||||
param = json_get_value_by_name((char *)payload, payload_len, "params", ¶m_len, NULL);
|
||||
if (NULL != param && 0 != param_len) {
|
||||
char reply_topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
prefix = json_get_value_by_name(param, param_len, ALCS_MQTT_JSON_KEY_PREFIX, &prefix_len, NULL);
|
||||
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && prefix)
|
||||
if (0 != alcs_remove_svr_key(alcs_mqtt_ctx->coap_ctx, prefix)) {
|
||||
}
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_del(ALCS_MQTT_JSON_KEY_PREFIX)) {
|
||||
COAP_ERR("Remove the keyprefix from aos_kv fail");
|
||||
;
|
||||
}
|
||||
|
||||
HAL_Snprintf(reply_topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_REPLY_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
__alcs_mqtt_send_response(reply_topic, atoi(reqid), 200, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
memset(topic_compare, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic_compare, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
|
||||
if ((strlen(topic_compare) == topic_len) && (strncmp(topic_compare, topic, topic_len) == 0)) {
|
||||
int param_len = 0, blacklist_len = 0, id_len = 0;
|
||||
char *param = NULL, *blacklist = NULL, *id = NULL;
|
||||
id = json_get_value_by_name((char *)payload, payload_len, "id", &id_len, NULL);
|
||||
|
||||
if (NULL != id && 0 != id_len) {
|
||||
strncpy(reqid, id, sizeof(reqid) - 1);
|
||||
}
|
||||
param = json_get_value_by_name((char *)payload, payload_len, "params", ¶m_len, NULL);
|
||||
if (NULL != param && 0 != param_len) {
|
||||
char reply_topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
blacklist = json_get_value_by_name(param, param_len, ALCS_MQTT_JSON_KEY_BLACK, &blacklist_len, NULL);
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && blacklist) {
|
||||
alcs_set_revocation(alcs_mqtt_ctx->coap_ctx, blacklist);
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(ALCS_MQTT_JSON_KEY_BLACK, blacklist, blacklist_len, 1)) {
|
||||
COAP_ERR("aos_kv_set set blacklist fail");
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_Snprintf(reply_topic, ALCS_MQTT_TOPIC_MAX_LEN,
|
||||
ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_REPLY_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
__alcs_mqtt_send_response(reply_topic, atoi(reqid), 200, NULL);
|
||||
} else {
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_BLACK, blacklist, &blacklist_len)) {
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx) {
|
||||
alcs_set_revocation(alcs_mqtt_ctx->coap_ctx, blacklist);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_subscribe(void *ctx, char *topic)
|
||||
{
|
||||
return (IOT_MQTT_Subscribe(NULL, topic, 0, __alcs_mqtt_subscribe_callback,
|
||||
ctx) < 0) ? ALCS_MQTT_STATUS_ERROR : ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static alcs_mqtt_status_e __alcs_mqtt_unsubscribe(void *ctx, char *topic)
|
||||
{
|
||||
return (mqtt_unsubscribe(topic) != 0) ? ALCS_MQTT_STATUS_ERROR : ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_init(void *handle, char *product_key, char *device_name)
|
||||
{
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
|
||||
if (handle == NULL || product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(alcs_mqtt_ctx_t));
|
||||
ctx->coap_ctx = (CoAPContext *)handle;
|
||||
memcpy(ctx->product_key, product_key, strlen(product_key));
|
||||
memcpy(ctx->device_name, device_name, strlen(device_name));
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_subscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_subscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_subscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
alcs_mqtt_prefixkey_update((void *)ctx->coap_ctx);
|
||||
alcs_mqtt_blacklist_update((void *)ctx->coap_ctx);
|
||||
|
||||
alcs_prefixkey_get(ctx->product_key, ctx->device_name);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_deinit(void *handle, char *product_key, char *device_name)
|
||||
{
|
||||
#if 0
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
|
||||
ARGUMENT_SANITY_CHECK(product_key && strlen(product_key), FAIL_RETURN);
|
||||
ARGUMENT_SANITY_CHECK(device_name && strlen(device_name), FAIL_RETURN);
|
||||
|
||||
if (handle == NULL || product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN || ctx == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_unsubscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_unsubscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_unsubscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
#endif
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void alcs_mqtt_add_srv_key(const char *prefix, const char *secret)
|
||||
{
|
||||
alcs_mqtt_ctx_t *alcs_mqtt_ctx = __alcs_mqtt_get_ctx();
|
||||
alcs_add_svr_key(alcs_mqtt_ctx->coap_ctx, prefix, secret, FROMCLOUDSVR);
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_blacklist_update(void *ctx)
|
||||
{
|
||||
CoAPContext *context = (CoAPContext *)ctx;
|
||||
char blacklist[ALCS_MQTT_BLACK_MAX_LEN] = {0};
|
||||
int blacklist_len = ALCS_MQTT_BLACK_MAX_LEN;
|
||||
|
||||
if (NULL == context) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_BLACK, blacklist, &blacklist_len)) {
|
||||
COAP_INFO("The blacklist is %.*s", blacklist_len, blacklist);
|
||||
if (blacklist_len) {
|
||||
alcs_set_revocation(context, blacklist);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_prefixkey_update(void *ctx)
|
||||
{
|
||||
CoAPContext *context = (CoAPContext *)ctx;
|
||||
char prefix[ALCS_MQTT_PREFIX_MAX_LEN] = {0};
|
||||
char secret[ALCS_MQTT_SECRET_MAX_LEN] = {0};
|
||||
int prefix_len = ALCS_MQTT_PREFIX_MAX_LEN, secret_len = ALCS_MQTT_SECRET_MAX_LEN;
|
||||
|
||||
if (NULL == context) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("start alcs_prefixkey_update\n");
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_PREFIX, prefix, &prefix_len) &&
|
||||
ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_SECRET, secret, &secret_len)) {
|
||||
COAP_INFO("The prefix is %.*s, deviceSecret is %.*s", prefix_len, prefix, secret_len, secret);
|
||||
if (prefix_len && secret_len) {
|
||||
alcs_add_svr_key(context, prefix, secret, FROMCLOUDSVR);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_prefixkey_get(const char *product_key, const char *device_name)
|
||||
{
|
||||
/* int ret = 0; */
|
||||
char *msg_pub = NULL;
|
||||
uint16_t msg_len = 0;
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
int id = ctx->send_id++;
|
||||
|
||||
if (product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_FMT,
|
||||
product_key, device_name);
|
||||
|
||||
msg_len = strlen(ALCS_MQTT_THING_ALCS_REQUEST) + 10 + 1;
|
||||
if ((msg_pub = ALCS_ADAPTER_malloc(msg_len)) == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
HAL_Snprintf(msg_pub, msg_len, ALCS_MQTT_THING_ALCS_REQUEST, id);
|
||||
|
||||
COAP_INFO("ALCS Prefix Get, Topic: %s, Payload: %s", topic, msg_pub);
|
||||
status = __alcs_mqtt_publish(topic, 1, msg_pub, strlen(msg_pub));
|
||||
|
||||
ALCS_free(msg_pub);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_subdev_prefix_get(const char *product_key, const char *device_name)
|
||||
{
|
||||
/* int ret = 0; */
|
||||
char *msg_pub = NULL;
|
||||
uint16_t msg_len = 0;
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
int id = ctx->send_id++;
|
||||
|
||||
if (product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("Subdevice, PK: %s, DN: %s\n", product_key, device_name);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
|
||||
msg_len = strlen(ALCS_MQTT_THING_ALCS_SUBDEV_REQUEST) + 10 + strlen(product_key) + strlen(device_name) + 1;
|
||||
if ((msg_pub = ALCS_ADAPTER_malloc(msg_len)) == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
HAL_Snprintf(msg_pub, msg_len, ALCS_MQTT_THING_ALCS_SUBDEV_REQUEST, id,
|
||||
(int)strlen(product_key), product_key, (int)strlen(device_name), device_name);
|
||||
|
||||
COAP_ERR("ALCS Prefix Get, Topic: %s, Payload: %s", topic, msg_pub);
|
||||
status = __alcs_mqtt_publish(topic, 1, msg_pub, strlen(msg_pub));
|
||||
|
||||
ALCS_free(msg_pub);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user